Question

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.

enter image description here

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top