首先是一点背景信息。我正在使现有的 C# 库代码适合在 WinRT 上执行。由于这段代码的一小部分需要做一些文件 IO,我们首先尝试保持同步并使用 Task.Wait() 来停止主线程,直到所有 IO 完成。
果然,我们很快就发现导致了死锁。
然后我发现自己在原型中更改了很多代码以使其“异步”。也就是说,我插入了 async 和 await 关键字,并相应地更改了方法返回类型。这是很多工作——事实上,太多毫无意义的工作——但我让原型以这种方式工作。
然后我做了一个实验,我在一个单独的线程上运行了带有 Wait 语句的原始代码:
System.Threading.Tasks.Task.Run(()=> Draw(..., cancellationToken)
没有僵局!
现在我很困惑,因为我认为我了解异步编程的工作原理。我们的代码(还)根本没有使用 ConfigureAwait(false)。所以所有 await 语句都应该在它们被调用时在相同的上下文中继续。对吗?我认为这意味着:相同的线程。现在如果这个线程调用了“Wait”,这也应该导致死锁。但事实并非如此。
你们中的任何人都有明确的坚如磐石的解释吗?
这个问题的答案将决定我是否真的会通过插入大量条件 async/await 关键字来搞乱我们的代码,或者我是否会保持它干净并只使用一个在这里和那里执行 Wait() 的线程。如果延续由任意非阻塞线程运行,那么事情应该没问题。但是,如果它们由 UI 线程运行,那么如果延续的计算成本很高,我们可能会遇到麻烦。
我希望这个问题很清楚。如果没有,请告诉我。