Task.WaitAll与异步挂起/等待任务
我必须缺少的东西SynchronizationContext
明显,像一个僵局,但我不明白为什么会发生,不明白我怎么能避免它...Task.WaitAll与异步挂起/等待任务
所以,应用程序是Azure WorkerRole(就我所知,本质上,通常的Windows应用程序没有UI)。在应用方面,我想平行多项任务,和我的代码的原理版本的执行是这样的:
private async Task DoJob()
{
await SomeIoOperation();
}
public void MethodExecutedByWorkerRoleInAnInfiniteLoop()
{
Log("Start");
Task.WaitAll(DoJob(), DoJob(), DoJob());
Log("End");
}
在这里,我的想法是,我们使用默认SynchronizationContext
操作的,所以我们应该避免例如,我们在类似的情况下会遇到的僵局。
但是,有时执行挂起 - 开始记录,结束不是天,直到我重新启动辅助角色。自然,DoJob无法运行那么久。奇怪的是,这并不是在工作者角色开始后立即发生 - 它可能需要几天或几周的正常操作直到它挂起。
我可以简化代码太多 - 也许重要的是什么发生在SomeIoOperation
- 但我觉得这是明显的与SynchronizationContext
误用有关。
请问SomeIoOperation.ConfigureAwait(false)
有帮助吗?我甚至无法测试它,因为我不知道它是否工作,因为问题已修复,或者最终会在几天后终止。
想法?
您正好处于SynchronizationContext的死锁状态。 只需使用WhenAll
代替WaitAll
:
public async Task MethodExecutedByWorkerRoleInAnInfiniteLoop()
{
Log("Start");
await Task.WhenAll(DoJob(), DoJob(), DoJob());
Log("End");
}
一切都将正常工作。
该方法在循环中执行 - 调用者希望知道方法何时完成。国际海事组织,这个修订应该返回'任务'。 – Gusdor
谢谢。我忘了在任务中更改无效。 –
但是在我的循环中,我将不得不执行'MethodExecutedByWorkerRoleInAnInfiniteLoop()。Wait()' - 它会不会导致死锁吗?据我所知,'Microsoft.WindowsAzure.ServiceRuntime'中没有'RoleEntryPoint'的异步版本,所以我无法在任何地方等待我的'MethodExecutedByWorkerRoleInAnInfiniteLoop'。 –
这篇文章将启发你的原因http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html – Gusdor
加入'Log(SynchronizationContext.Current);'if它不是'null',你会知道你有'SynchronizationContext'问题。 – i3arnon
'DoJob'将总是希望与调用上下文同步。 SomeIoOperation使用哪个上下文并不重要。 – Gusdor