我在代码中遇到死锁问题。
我的代码如下所示:
public async Task DoStuff(input)
{
await AsyncMethod();
//internally calls an async method, and blocks for its return. sometimes couses deadlocks.
new MyService().DoMoreStuff();
}
MyService.DoMoreStuff实现:
DoMoreStuff()
{
return DoSuffAsyncMethod().Result;
}
这段代码有时使我在DoSuffAsyncMethod上陷入僵局,
在MyService.DoMoreStuff方法中。
但是,如果我将有问题的代码包装在任务中,则不再发生死锁
public async Task DoStuff(input)
{
await AsyncMethod();
await Task.Run(new MyService().DoMoreStuff());
}
更多信息
此代码在Windows服务的上下文中运行
因此,不涉及同步上下文。
我知道如何解决该问题,但仍然不明白为什么代码会陷入僵局。
没有人可以对没有同步上下文的混合同步异步代码的僵局提出解释吗?
编辑
感谢您的评论。
我认为这是僵局。
实际情况稍微复杂一点,所以我简化了一下。
在DoSuffAsyncMethod()中,在经过一些预定义的时间后,我们正在调用远程异步服务-我们正在超时。
分析请求和接收服务后,发现消息实际上已正确传输。
因此,除非出现与网络或网络框架相关的问题,否则我们将陷入僵局。
我们假设这是死锁,因为一旦我们重新构造了代码,DoSuffAsyncMethod中的超时就消失了。
编辑2
代码
DoSuffAsyncMethod().Wait().Result
是错的。
正确的代码是
DoSuffAsyncMethod().Result
问题是由于在调用堆栈的更深层调用了ConfigureAwait(true)。
谢谢您的帮助。
最佳答案
await
的基本含义是:“嘿,thread
继续做您的工作,当我准备好时,我会要求您继续工作”。线程就像:“是的,但是当我完成剩余的工作后,我会来找你的”。然后,您要求线程Wait
完成上一个任务,但是它将永远无法完成工作,因为要完成该任务需要线程返回给他(是的,正在等待它的线程...)
但是当你这样做
await Task.Run(new MyService().DoMoreStuff());
await
之后的线程可用于恢复先前等待的任务(DoMoreStuff()
),因此它们都能够完成其工作。更多信息,也许更好的解释可以找到here