Task.Wait() 没有 Task.Run 包装就不起作用



我有一个方法taskdowork ():

public Task DoWork() => Call();
private async Task Call()
{
await DoAnotherWorkAsync()
}

然后我在项目的另一部分使用这个方法,像这样:

public void Execute(ref param1, ref param2)
{
...
someInstance.DoWork().Wait();
}

它不工作(只是等待太长时间)。但是下面的代码工作得非常正确:

public void Execute(ref param1, ref param2)
{
...
Task.Run(async => await someInstance.DoWork()).Wait();
}

谁能解释这种行为并建议如何修复它?谢谢。

正如我在博客文章《不要阻塞异步代码》中解释的那样,Wait()可能会导致死锁。这种死锁将发生在以下情况:1)await捕获的单线程上下文,以及2)阻塞代码(Wait())在调用堆栈的更上层。

Task.Run工作的原因是委托在线程池线程上运行,它没有单线程上下文。

最好的解决方案是完全不阻塞

如果这是一个UI应用,那么使用一个不同的UX模式(例如,显示一个"loading…"或"执行……"指示符,然后在异步工作完成时更新UI)。阻塞UI线程被认为是糟糕的UX(如果这是一个移动应用,可能会导致应用商店拒绝)。

如果这是一个服务器端应用程序,那么使用await而不是阻塞,让async/await一直向上传播。

最新更新