29

Async/Await FAQで、Stephen Toub は次のように述べています。

awaitableは、有効なawaiterGetAwaiterを返すメソッドを公開する任意の型です
...
awaiterはawaitableメソッドから返される任意の型であり、特定のパターンに準拠します。GetAwaiter

したがって、awaiterになるためには、タイプは次のようにする必要があります。

  • インターフェイスを実装しINotifyCompletionます。
  • というブール値のプロパティを提供しますIsCompleted
  • またはGetResultを返すパラメータなしのメソッドを提供します。voidTResult

(今は無視しICriticalNotifyCompletionています。 )

私が言及したページには、コンパイラが await 操作をどのように変換するかを示すサンプルがあることは知っていますが、まだ理解するのに苦労しています。

私がawaitableを待っているとき、

  • いつIsCompletedチェックされますか?どこに設定すればよいですか?
  • いつOnCompleted呼ばれますか?
  • どのスレッドが を呼び出しOnCompletedますか?
  • の継続パラメーターを直接呼び出す例と、さまざまな例でOnCompleted使用する例を見ました。Task.Run(continuation)
4

2 に答える 2

16

なぜカスタム awaiter が必要なのですか?

await ここでコンパイラの解釈を見ることができます。基本的に:

var temp = e.GetAwaiter();
if (!temp.IsCompleted)
{
  SAVE_STATE()
  temp.OnCompleted(&cont);
  return;

cont:
  RESTORE_STATE()
}
var i = temp.GetResult();

コメントから編集: OnCompleted引数を非同期操作の継続としてスケジュールする必要があります。

于 2012-09-30T13:00:38.857 に答える
6

ほとんどの場合、開発者はこれについて心配する必要はありません。asyncandキーワードを使用するawaitと、コンパイラとランタイムがこれらすべてを処理します。

質問に答えるには:

コードはいつ IsCompleted をチェックしますか? どこに設定すればよいですか?

IsCompletedタスクは、タスクが実行していたことを完了したときに設定する必要があります。たとえば、タスクがファイルからIsCompletedデータをロードしていた場合、データがロードされ、呼び出し元がアクセスできる場合は true を返す必要があります。

OnCompleted はいつ呼び出されますか?

OnCompleted には、通常、タスクの完了時に実行する呼び出し元によって提供されるデリゲートが含まれています。

OnCompleted を並行して呼び出しますか、それとも OnCompleted 内のコードを非同期にする必要がありますか?

OnCompleted のコードは、スレッド ニュートラルにする必要があります (どのスレッドから呼び出されるかは気にしません)。これは、シングル スレッド アパートメント (Metro/Windows8/Windows ストア アプリの UI クラスなど) で COM オブジェクトを更新する場合に問題になる可能性があります。非同期である必要はありませんが、非同期コードを含めることができます。

OnCompleted の継続パラメーターを直接呼び出す例と、さまざまな例で Task.Run(continuation) を使用する例を見ました。

可能な場合はasync/を使用してください。awaitそれ以外の場合は、Task.Run() または Task.Wait() を使用します。これは、ほとんどの人が慣れ親しんでいるシーケンシャル プログラミング モデルに従っているためです。特にアパートメントの問題がある Metro アプリでは、引き続き継続を使用する必要がある場合があります。

于 2012-09-30T13:05:53.003 に答える