I have following SignalR code for desktop client:
_hub.On<String>("Ping",(string s) =>
{
Console.WriteLine(s + " from MainHub ");
_hub.Invoke("Acknowledge","Say Hello to MainHub");
});
I have Ping and Acknowledge method on Hub.
But
_hub.Invoke("Acknowledge","Say Hello to MainHub");
is not firing properly from desktop client.
How to write this code properly?
As per this Link
Currently in the .NET client we serialize invoking user callbacks upon receiving messages from the server using a TaskQueue. This includes callbacks registered using HubProxy.On or continuations after HubProxy.Invoke.
If these callbacks block, especially blocking waiting on result from another callback, the receive dispatch queue will simply stop (deadlock).
We should detect this condition and trace an error when it occurs (Connection.OnError).
We could do this in the TaskQueue itself (with an optional flag that enables it of course) that makes it essentially monitor itself, using an async loop started on the first enqueue that checks if the task currently running is the same as what was running on the last interval. If so, log the error.
Now I have managed to fix this issue by a quick but dirty solution. I know this is not the way to fix this issue, but I dont have any choices other than this. Other solution better than this is higly appreciated.
Threading.Timer tmr= new Threading.Timer(new TimerCallback(Acknowledge),null, 0, Timeout.Infinite);
private void Acknowldege(object state)
{
if(SignalRIsReady)//check if signalr is ready
{
_hub.Invoke("Acknowledge","Say Hello to MainHub");
tmr.Change(Timeout.Infinite, Timeout.Infinite);//wait until next event occurs
}
}
_hub.On<String>("Ping",(string s) =>
{
Console.WriteLine(s + " from MainHub ");
tmr.Change(50, Timeout.Infinite);// call callback after 50ms
});
Another Solution I have managed is using configureawait. Following is the solution:
_hub.On<String>("Ping",async(string s) =>
{
Console.WriteLine(s + " from MainHub ");
await Task.Run(async()=>{
_hub.Invoke("Acknowledge","Say Hello to MainHub");
}).ConfigureAwait(false);//this will run the task to seperate thread, unblocking the parent thread
});
Related
works here -----
crashes here -----
So i am making this server client chat system based on message queue and in client side, i have a thread that receives messages. The name of my listbox is 'displaymsg'
here's my thread pool method
public void getmsg(object ob)
{
string msg = "";
while (true)
{
msg = mRecieve.GetMessages();
displaymsg.Items.Add(msg);
}
}
But the program is crashing when it reaches to displaymsg.Items.Add(msg) part.
To check if it is even reaching there and if it is working fine, i replaced it with MessageBox.Show(msg), and it is working fine, i receive every message in a pop up box that i send from other end. I'm new to wpf so kinda lost now... please help!!
You can not access a control from a non-UI thread. You have to use a dispatcher to marshal it back to the UI thread:
displaymsg.Dispatcher.Invoke(() => displaymsg.Items.Add(msg));
You can also fire and forget if you don‘t want to wait for the result:
displaymsg.Dispatcher.BeginInvoke(() => displaymsg.Items.Add(msg));
There is a WCF service that is hosted in a .Net Console application. The client creates a duplex channel to the service that has a callback. It calls the service in this way:
var task = Task<object>.Factory.FromAsync(clientRay.Proxy.BeginCalc, clientRay.Proxy.EndCalc, lst_RaySrvcDetails, state);
And here is the Main method of the service Console app:
static void Main(string[] args)
{
ServiceHost srvcHost = new ServiceHost(serviceInstance, uriBase);
//
//Here the service is hosted
//
while(true)
{
;
}
}
And the MyService.cs receives the call in the below method:
public IAsyncResult BeginCalc(List<MBSWaldram.DataAccessLayer.Framework.ServiceDetails> input,
AsyncCallback callback, object state)
{
calcInput = input;
// Create a task to do the work
var task = Task<object>.Factory.StartNew(this.CalcTasks, state);
return task.ContinueWith(res => callback(task));
}
Now the CalcTasks method, where the actual task is run, is showing less performance compare to have it on a WCF Windows Form application. One of the reason I can think of is the way I have used while(true){;} infinite loop so that the application doesn't terminates and waits for the call from the client. Not sure this the best of doing it. For some reason I can't use Windows Form Application.
I appreciate if anyone could shed some light in why there is a performance issue here.
Thanks.
while (true) {;} is really unlucky construction. In Console application take Console.ReadLine() instead. The application will wait until Enter press.
I have successfully created an Azure application that sends DbTransactions to a ServiceBus Queue, and then, enqueues a 'notifying message' to a ServiceBus Topic for other clients to monitor (...so they can receive the updates automatically).
Now, I want to use SignalR to monitor & receive the SubscriptionClient messages...and I have test-code that works just fine on its' own.
I have found many examples for sending messages to an Azure Queue (that is easy). And, I have the code to receive a BrokeredMessage from a SubscriptionClient. However, I cannot get SignalR to continuously monitor my Distribute method.
How do I get SignalR to monitor the Topic?
CODE BEHIND: (updated)
public void Dequeue()
{
SubscriptionClient subscription = GetTopicSubscriptionClient(TOPIC_NAME, SUBSCRIPTION_NAME);
subscription.Receive();
BrokeredMessage message = subscription.Receive();
if (message != null)
{
try
{
var body = message.GetBody<string>();
var contextXml = message.Properties[PROPERTIES_CONTEXT_XML].ToString();
var transaction = message.Properties[PROPERTIES_TRANSACTION_TYPE].ToString();
Console.WriteLine("Body: " + body);
Console.WriteLine("MessageID: " + message.MessageId);
Console.WriteLine("Custom Property [Transaction]: " + transaction);
var context = XmlSerializer.Deserialize<Person>(contextXml);
message.Complete();
Clients.All.distribute(context, transaction);
}
catch (Exception ex)
{
// Manage later
}
}
}
CLIENT-SIDE CODE:
// TEST: Hub - GridUpdaterHub
var hubConnection = $.hubConnection();
var gridUpdaterHubProxy = hubConnection.createHubProxy('gridUpdaterHub');
gridUpdaterHubProxy.on('hello', function (message) {
console.log(message);
});
// I want this automated
gridUpdaterHubProxy.on('distribute', function (context, transaction) {
console.log('It is working');
});
connection.start().done(function () {
// This is successful
gridUpdaterHubProxy.invoke('hello', "Hello");
});
I would not do it like that. Your code is consuming and retaining ASP.NET thread pool's threads for each incoming connection, so if you have many clients you are not scaling well at all. I do not know the internals of SignalR that deep, but I'd guess that your never-ending method is preventing SignalR to let the client call your callbacks because that needs the server method to end properly. Just try to change while(true) with something exiting after, let's say, 3 messages in the queue, you should be called back 3 times and probably those calls will happen all together when your method exits.
If that is right, then you can move to something different, like dedicating a specific thread to consuming the queue and having callbacks called from there usning GlobalHost.ConnectionManager.GetHubContext. Probably better, you could try a different process consuming the queue and doing HTTP POST to your web app, which in turns broadcasts to the clients.
I am writing a little WPF application to test some SignalR code. Everything works from what I have written, but I have stumbled across something which I am unsure of.
I have created an event handler for the HubConnection StateChanged event;
_hub.StateChanged += (change) =>
{
Console.WriteLine("hubConnection.StateChanged {0} => {1}", change.OldState, change.NewState);
if (change.NewState == ConnectionState.Connecting)
{
statusCallBack callBack = new statusCallBack(UpdateStatus);
this.Dispatcher.Invoke(callBack, "hubConnection.StateChanged");
}
if (change.NewState == ConnectionState.Connected)
{
Console.WriteLine("hello");
statusCallBack callBack = new statusCallBack(UpdateStatus);
this.Dispatcher.Invoke(callBack, "hubConnection.StateChanged");
}
};
With my Delegate method statusCallBack and method being;
delegate void statusCallBack(string msg);
private void UpdateStatus(string msg)
{
if (this.Dispatcher.CheckAccess() == true)
{
this.tbStatus.AppendText(Environment.NewLine + DateTime.Now.ToLongTimeString() + " --- " + msg);
this.tbStatus.CaretIndex = this.tbStatus.Text.Length;
this.tbStatus.ScrollToEnd();
}
}
Now I am probably missing something really obvious here, but when in the StateChanged handler I check for ConnectionState.Connecting and output the message to my Label it works fine.
Then when the SignalR HubConnection state then changes to ConnectionState.Connected and I try to Invoke the delegate, the WPF app just locks up.
It will output to the console fine, and check to see if change.NewState == ConnectionState.Connected, then will output "hello" to the console, but then just freezes.
If I debug the app, when it gets to within the Connected if statement, the object change.NewState and change.OldState have the error message below.
View larger image here.
I am lost as to why it works within the first if statement, but not the second. Also why it is able to output the correct values to the console?
Even if I comment out the initial if statement to check for Connecting it will still freeze when Connected.
This is a common deadlock problem when calling back to the UI from an event.
Try using Dispatcher.BeginInvoke rather than Invoke.
As quoted in this thread:
When you use Dispatcher.BeginInvoke it means that it schedules the
given action for execution in the UI thread at a later point in time,
and then returns control to allow the current thread to continue
executing. Invoke blocks the caller until the scheduled action
finishes.
As a side-note: MVVM Light has a very useful helper called DispatcherHelper that is not only compatible with virtually everything (WPF, WinRT, SL, etc.), but very simple to use. It helps you automatically dispatch calls back to the UI. If nothing else, it may be helpful to use the NUGet package JUST for this feature.
I'm making an application that will monitor the state of another process and restart it when it stops responding, exits, or throws an error.
However, I'm having trouble to make it reliably check if the process (Being a C++ Console window) has stopped responding.
My code looks like this:
public void monitorserver()
{
while (true)
{
server.StartInfo = new ProcessStartInfo(textbox_srcdsexe.Text, startstring);
server.Start();
log("server started");
log("Monitor started.");
while (server.Responding)
{
if (server.HasExited)
{
log("server exitted, Restarting.");
break;
}
log("server is running: " + server.Responding.ToString());
Thread.Sleep(1000);
}
log("Server stopped responding, terminating..");
try
{ server.Kill(); }
catch (Exception) { }
}
}
The application I'm monitoring is Valve's Source Dedicated Server, running Garry's Mod, and I'm over stressing the physics engine to simulate it stopping responding.
However, this never triggers the process class recognizing it as 'stopped responding'.
I know there are ways to directly query the source server using their own protocol, but i'd like to keep it simple and universal (So that i can maybe use it for different applications in the future).
Any help appreciated
The Responding property indicates whether the process is running a Windows message loop which isn't hung.
As the documentation states,
If the process does not have a MainWindowHandle, this property returns true.
It is not possible to check whether an arbitrary process is doing an arbitrary thing, as you're trying to.