.Wait()和.GetAwaiter()之间有什么区别.GetResult()?

66 c# multithreading asynchronous

我的方法返回Task.我想等到它完成.我应该使用 .Wait()或.GetAwaiter().GetResult()?他们之间有什么区别?

Lua*_*aan 78

两者都是同步等待操作的结果(如果可能的话,你应该避免这些).

差异主要在于处理异常.有了Wait,异常堆栈跟踪没有改变,并代表异常时的实际堆栈,所以如果你有一段代码在一个线程池线程上运行,你就有一个类似的堆栈

ThreadPoolThread.RunTask
YourCode.SomeWork
Run Code Online (Sandbox Code Playgroud)

另一方面,.GetAwaiter().GetResult()将重新编写堆栈跟踪以考虑所有异步上下文,忽略代码的某些部分在UI线程上执行,而某些部分在ThreadPool线程上执行,而某些部分只是异步I/O. 因此,您的堆栈跟踪将反映代码中的同步步骤:

TheSyncMethodThatWaitsForTheAsyncMethod
YourCode.SomeAsyncMethod
SomeAsync
YourCode.SomeWork
Run Code Online (Sandbox Code Playgroud)

至少可以说,这往往会使异常堆栈跟踪更加有用.您可以在应用程序的上下文中查看YourCode.SomeWork调用的位置,而不是"它运行的物理方式".

这是如何工作的一个例子是在参考源(当然是非契约的).

  • @DavidRR整个`TaskAwaiter`是一个实现细节.另一方面,awaitable/awaiter机制被记录下来,并且使用duck-typing - `GetAwaiter`是'await`,因为`GetEnumerator`是`foreach`或`Dispose`是`using`.所有这些都在C#规范中定义,无论使用何种特定的awaiter - 请注意`Task.GetAwaiter`是"用于编译器而不是用于应用程序代码".但问题是,预期的用途是做一个`await`,而不是`Wait()`或`GetAwaiter().GetResult()` - 但是如果你需要它,`GetResult`会给你更好的堆栈. (18认同)
  • [Task.GetAwaiter()](https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.getawaiter%28v=vs.110%29.aspx)返回[TaskAwaiter]( https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.taskawaiter%28v=vs.110%29.aspx).但是,[TaskAwaiter.GetResult()](https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.taskawaiter.getresult%28v=vs.110%29.aspx)的文档建议:*"此API支持产品基础结构,不能直接在您的代码中使用."*您能评论吗? (5认同)
  • @Luaan `using` 和 `Dispose()` 不使用鸭子类型。这只在实现“IDisposable”时才有效。Ducktyping 用于“foreach”和“GetEnumerator()”,以及“await”和“GetAwaiter()”。 (2认同)