【问题标题】:Why doesn't ConfigureAwait(false) prevent deadlock if it's inside an iteration?如果在迭代中,为什么 ConfigureAwait(false) 不能防止死锁?
【发布时间】:2016-01-18 00:08:08
【问题描述】:

有人可以解释为什么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);
        }
    });
} 

【问题讨论】:

    标签: c# asp.net .net async-await task


    【解决方案1】:

    AsyncMethod2 中的 await 正在返回其上下文。我指的是实际上在AsyncMethod2 中的await - 即await Task.Run(...);。该await 没有ConfigureAwait(false),因此它将恢复到其上下文。

    循环中是否有ConfigureAwait(false) 无关紧要,因为该循环在没有上下文的线程池线程 (Task.Run) 上运行。

    【讨论】:

    • 非常感谢 :) 我想确保我明白了 - 当 await Task.Run(...) 的等待返回到它的上下文时 - 发生了死锁,对吧?因为该上下文被BlockingMethod(...) 捕获。对吗?
    • @shay__:上下文由AsyncMethod2 捕获。更准确地说,它被await Task.Run(...) 语句捕获。请记住,await Task.Run(...); 本质上与var runTask = Task.Run(...); await runTask; 相同,并且上下文在await runTask; 之前立即被捕获,并用于在await runTask; 之后立即恢复方法。
    • 所以现在我更加困惑了,哈哈。 await Task.Run(...) 捕获上下文 - 谁是第二个尝试恢复到该上下文的任务?
    • @shay__:async 方法 (AsyncMethod2) 在上下文中恢复。没有“第二个任务”。您可能会发现我的async intro 很有帮助。
    • @shay__:我在我的don't block on async code 博客文章中解释了这种死锁。你们有两件事在等着对方:一是在BlockingMethod 内对Task.Wait 的调用;另一个是AsyncMethod2返回的任务。任务正在等待上下文释放,线程被阻塞(持有该上下文)等待任务完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 2022-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多