在异步操作后立即调用Task.Wait(),相当于同步运行相同的操作
本文关键字:同步 相当于 运行 操作 异步操作 调用 Wait Task | 更新日期: 2023-09-27 18:02:47
换句话说,是
var task = SomeLongRunningOperationAsync();
task.Wait();
与
功能相同SomeLongRunningOperation();
换句话说,是
var task = SomeOtherLongRunningOperationAsync();
var result = task.Result;
与
功能相同var result = SomeOtherLongRunningOperation();
根据任务。等待和内联,如果Wait
上的任务已经开始执行,Wait
必须阻塞。然而,如果它还没有开始执行,Wait
可能能够将目标任务从它排队的调度程序中拉出来,并在当前线程上内联执行它。
这两种情况是否仅仅是决定任务将在哪个线程上运行的问题,如果您正在等待结果,这是否重要?
如果在异步调用和Wait()
之间不执行任何操作,那么使用异步形式比同步形式有什么好处吗?
以下是一些不同之处:
- 计算可能在不同的线程上运行。如果此任务基于cpu并且可以内联,则它可能在同一线程上运行。这是不确定的。
- 如果没有发生内联,则在计算期间将使用另一个线程。这通常需要1MB堆栈内存。
- 异常将被包装在
AggregateException
中。异常堆栈将会不同。 - 如果计算提交到当前同步上下文,任务版本可能会死锁
- 如果线程池已满,如果要完成任务必须安排另一个任务,则可能会死锁。
- 线程本地状态,如
HttpContext.Current
(实际上不是线程本地,但几乎),可能是不同的。主线程的线程中止将无法到达任务体(内联的情况除外)。我不确定等待本身是否会被终止。 创建
Task
会产生内存屏障,从而产生同步效果。这有关系吗?根据这个列表你自己决定。
这样做有什么好处吗?我想不起来。如果你的计算使用异步IO,等待将抵消异步IO带来的好处。一个例外是扇形输出IO,例如并行发出10个HTTP请求并等待它们。这样,你就以一个线程为代价进行了10次操作。
请注意,Wait
和Result
在所有这些方面都是等效的。