2016-04-05 19 views

答えて

33

両方とも、操作結果の同期待機です(可能な場合は、これらを避ける必要があります)。

違いは主に例外処理です。 Waitでは、例外スタックトレースは不変であると例外が発生したときの実際のスタックを表し、そうあなたは、スレッドプールのスレッド上で実行されるコードの部分を持っている場合、あなたは

ThreadPoolThread.RunTask 
YourCode.SomeWork 
のようなスタックを持っていると思います

一方、.GetAwaiter().GetResult()は、コードの一部がUIスレッド上で実行され、一部がThreadPoolスレッド上で実行されることを無視して、すべての非同期コンテキストを考慮に入れてスタックトレースを再作成します。また、単に非同期I/O 。だからあなたのスタックトレースはあなたのコードて、同期のようなステップを反映します:

TheSyncMethodThatWaitsForTheAsyncMethod 
YourCode.SomeAsyncMethod 
SomeAsync 
YourCode.SomeWork 

これは例外スタックを作る傾向がある、控えめに言っても、多くの便利なトレース。 「実行された物理的な方法」ではなく、アプリケーションのコンテキストで、YourCode.SomeWorkと呼ばれた場所を確認できます。

これがどのように機能するかの例は、reference source(非契約型です)にあります。

+4

[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は製品インフラストラクチャをサポートしており、コードから直接使用するためのものではありません。" *コメントできますか? – DavidRR

+7

@DavidRR 'TaskAwaiter'は実装の詳細です。一方、待ち受け/待ち受けのメカニズムは文書化され、ダックタイピングを使用します。GetAniteratorはGetEnumeratorがforeachになるか、Disposeが「使用する」ために待機します。これはすべて、C#の仕様で定義されています。使用する特定の待ち時間に関係なく、「Task.GetAwaiter」は「アプリケーションコードで使用するのではなく、コンパイラでの使用を意図しています」ということに注意してください。しかし要点は、Wait()やGetAwaiter()。GetResult()ではなく、 'await'を使うことです。必要な場合には' GetResult'でより良いスタックを得ることができます。 – Luaan

関連する問題