为什么 ConfigureAwait(false) 在迭代中不能防止死锁?
Why doesn't ConfigureAwait(false) prevent deadlock if it's inside an iteration?
有人可以解释为什么 AsyncMethod2
会导致死锁吗?我(想我)明白 AsyncMethod1
中的顶级任务不会尝试在 BlockingMethod
捕获的上下文中继续执行它,因此避免了死锁,但我不明白是什么AsyncMethod2
的幕后故事:
private static void BlockingMethod(IEnumerable<Object> data)
{
AsyncMethod1(data).Wait(); // no deadlock
AsyncMethod2(data).Wait(); // deadlock
}
private static async Task AsyncMethod1(IEnumerable<Object> data)
{
await Task.Run(async () =>
{
foreach (var obj in data)
{
await AsyncMethod2.(obj);
}
}).ConfigureAwait(false);
}
private static async Task AsyncMethod2(IEnumerable<Object> data)
{
await Task.Run(async () =>
{
foreach (var obj in data)
{
await AsyncMethod2.(obj).ConfigureAwait(false);
}
});
}
AsyncMethod2
中的 await
正在返回其上下文。我指的是实际上在 AsyncMethod2
中的 await
- 即 await Task.Run(...);
。 await
没有 ConfigureAwait(false)
,因此它将恢复到其上下文。
循环中是否有 ConfigureAwait(false)
并不重要,因为该循环在线程池线程 (Task.Run
) 上运行,无论如何都没有上下文。
有人可以解释为什么 AsyncMethod2
会导致死锁吗?我(想我)明白 AsyncMethod1
中的顶级任务不会尝试在 BlockingMethod
捕获的上下文中继续执行它,因此避免了死锁,但我不明白是什么AsyncMethod2
的幕后故事:
private static void BlockingMethod(IEnumerable<Object> data)
{
AsyncMethod1(data).Wait(); // no deadlock
AsyncMethod2(data).Wait(); // deadlock
}
private static async Task AsyncMethod1(IEnumerable<Object> data)
{
await Task.Run(async () =>
{
foreach (var obj in data)
{
await AsyncMethod2.(obj);
}
}).ConfigureAwait(false);
}
private static async Task AsyncMethod2(IEnumerable<Object> data)
{
await Task.Run(async () =>
{
foreach (var obj in data)
{
await AsyncMethod2.(obj).ConfigureAwait(false);
}
});
}
AsyncMethod2
中的 await
正在返回其上下文。我指的是实际上在 AsyncMethod2
中的 await
- 即 await Task.Run(...);
。 await
没有 ConfigureAwait(false)
,因此它将恢复到其上下文。
循环中是否有 ConfigureAwait(false)
并不重要,因为该循环在线程池线程 (Task.Run
) 上运行,无论如何都没有上下文。