Wait()导致UI线程挂起 - 何时应该使用Wait()?

时间:2014-03-28 07:39:54

标签: c# .net task-parallel-library signalr async-await

我有以下连接到SignalR Hub的代码

    private static async Task StartListening()
    {
        try
        {


            var hubConnection = new HubConnection("http://localhost:8080/");                
            IHubProxy hubProxy = hubConnection.CreateHubProxy("Broadcaster");
            hubProxy.On<EventData>("notifyCardAccessEvent", eventData =>
            {
                Log.Info(string.Format("Incoming data: {0} {1}", eventData.Id, eventData.DateTime));
            });
            ServicePointManager.DefaultConnectionLimit = 10;
            await hubConnection.Start();
            Log.Info("Connected");
        }
        catch (Exception ex)
        {
            Log.Error(ex);
        }
    }

在我的Form_Load方法中,我有这个

StartListening();

然而,Resharper提醒我要考虑应用“等待”#39;操作员调用结果&#34;

所以我这样做了:

Log.Info("Connecting to SignalR hub...");
StartListening().Wait();
Log.Info("Connected!");

但是,这会导致我的UI线程挂起,Connected!永远不会打印到日志文件中。

所以我的问题是,我应该何时使用Wait()?我应该使用Wait()的实例和场景是什么,何时不应该使用Wait()

3 个答案:

答案 0 :(得分:5)

await不是Wait。目前还不清楚调用StartListening()的代码是什么,但有一个选项是await,如建议的那样:

await StartListening();

但是,在其他一些情况下,最好什么都不做:

StartListening(); // drop the Task on the floor

或者可能使用ContinueWith进行手动延续。由于StartListening方法会捕获任何异常,因此忽略返回的Task并没有任何问题 - 所以您已经拥有了。不过,我建议将其称为StartListeningAsync

死锁的原因是如果你使用Wait,你的UI线程会阻塞等待异步方法完成,但是这个异步方法正在捕获同步上下文,这意味着为了处理每个延续它试图进入UI线程 - 它被阻止...... 就此

答案 1 :(得分:4)

@MarcGravell有正确的答案;我只想回答这个问题:

  

所以我的问题是,我什么时候应该使用Wait()?我应该使用Wait()的实例和场景是什么,何时不应该使用Wait()?

混淆来自于Task类型用于两个几乎完全不同的事物。

Task最初是作为任务并行库的一部分在.NET 4.0中引入的。通常,您可以使用并行LINQ或Parallel类进行并行处理(使用下面的Task类型)。但是,in advanced scenarios, you could use the Task type directlyTask.Wait用于等待完成这些独立任务。

在.NET 4.5中引入async / await时,现有的Task类型几乎足以用作抽象&#34 ;未来&#34 ;.因此,不要发明一些新的&#34;未来&#34;类型,他们只是略微扩展Task以作为未来。

这将我们带到今天,其中Task可以用作:

  • 并行计算中的工作项目。
  • 异步未来。

(还有一点点交叉:您可以将并行工作视为异步,在极少数情况下,例如Console Main方法,您需要阻止异步任务;但暂时忽略这些。 )

这意味着Task的API会按这些行分开。 StartWaitResultContinueWith等成员非常坚定地站在并行方面。在异步世界中,await更合适。

我的async intro底部有一个小表,它有一些新的(异步)等效的旧(并行)方式。

答案 2 :(得分:1)

你好像误解了来自Resharper的消息。您调用了await方法,而不是应用Task.Wait()运算符。他们可能看起来很相似,但他们的工作完全不同。

这个不错的答案将提供有关差异的更多信息:https://stackoverflow.com/a/13140963/3465395