我有一个方法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
一直向上传播。