SignalR WPF StateChange问​​题

时间:2013-08-16 13:53:47

标签: c# signalr dispatcher signalr.client

我正在编写一个小的WPF应用程序来测试一些SignalR代码。一切都与我所写的一致,但我偶然发现了一些我不确定的东西。

我为HubConnection StateChanged事件创建了一个事件处理程序;

_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");
    }
};

使用我的Delegate方法statusCallBack和方法;

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();
    }
}

现在我可能遗漏了一些非常明显的东西,但是当我在StateChanged处理程序中检查ConnectionState.Connecting并将消息输出到我的Label时,它工作正常。

然后当SignalR HubConnection状态变为ConnectionState.Connected并尝试调用委托时,WPF应用程序就会锁定。

它会很好地输出到控制台,并检查是否change.NewState == ConnectionState.Connected,然后将“hello”输出到控制台,然后冻结。

如果我调试应用,当它进入Connected if语句时,对象change.NewStatechange.OldState会出现以下错误消息。

enter image description here

View larger image here.

我迷失了为什么它在第一个if语句中起作用,但不是第二个。为什么它能够将正确的值输出到控制台?

即使我发表评论if的初始Connecting语句,它仍会在Connected时冻结。

1 个答案:

答案 0 :(得分:2)

从事件回调UI时,这是一个常见的死锁问题。

尝试使用Dispatcher.BeginInvoke而不是Invoke

引用this帖子:

  

当您使用Dispatcher.BeginInvoke时,它意味着它会安排   给定在稍后的UI线程中执行的操作,   然后返回控件以允许当前线程继续   执行。调用会阻止调用者直到计划的操作   饰面。

作为旁注:MVVM Light有一个非常有用的帮助程序DispatcherHelper,它不仅与几乎所有东西(WPF,WinRT,SL等)兼容,而且使用起来非常简单。它可以帮助您自动将呼叫分配回UI。如果不出意外,使用NUGet软件包JUST可能会对此功能有所帮助。