0

我正在编写一个小 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消息并将其输出到我的标签时,它工作正常。

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

它将正常输出到控制台,并检查是否change.NewState == ConnectionState.Connected,然后将“hello”输出到控制台,但随后就冻结了。

如果我调试应用程序,当它进入 Connectedif语句时,对象change.NewStatechange.OldState在下面显示错误消息。

在此处输入图像描述

在此处查看大图。

我不知道为什么它在第一个 if 语句中起作用,而不是第二个。还有为什么它能够将正确的值输出到控制台?

即使我注释掉初始if语句以检查Connecting它仍然会在Connected.

4

1 回答 1

2

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

尝试使用Dispatcher.BeginInvoke而不是Invoke.

正如此线程中所引用的:

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

附带说明:MVVM Light 有一个非常有用的帮助器,称为DispatcherHelper它不仅与几乎所有东西(WPF、WinRT、SL 等)兼容,而且使用起来非常简单。它可以帮助您自动将调用分派回 UI。如果不出意外,将 NUGet 包仅用于此功能可能会有所帮助。

于 2014-08-05T15:12:23.623 回答