2015-10-19 74 views
-1

有人可以解释为什么AsyncMethod2会导致死锁?我(想我)明白AsyncMethod1中的顶级任务不会尝试在BlockingMethod捕获的上下文中执行它的延续,因此可以避免死锁,但我不明白AsyncMethod2引擎盖下发生了什么:如果ConfigureAwait(false)在迭代中,那么为什么不防止死锁?

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); 
     } 
    }); 
} 

回答

4

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

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

+0

非常感谢:)我想确保我得到它 - 当await Task.Run(...)返回到它的上下文时,会发生死锁,对吗?因为该上下文被'BlockingMethod(...)'捕获。那是对的吗? –

+0

@shay__:上下文由'AsyncMethod2'捕获。更确切地说,它被'await Task.Run(...)'语句捕获。请记住,'await Task.Run(...);'与var runTask = Task.Run(...)基本相同; await runTask;'并且在'await runTask;'之前立即捕获上下文,并且用于在'await runTask;'之后立即恢复该方法。 –

+0

所以现在我更加困惑,哈哈。 '等待Task.Run(...)'捕获上下文 - 谁是第二个尝试恢复到上下文的任务? –

相关问题