web-dev-qa-db-ja.com

SynchronizationContextを使用するタスクを取得する方法そして、とにかくSynchronizationContextはどのように使用されますか?

タスクコンセプトとTPLの全体をまだ学習しています。私の現在の理解から、SynchronizationContext関数(存在する場合)はawaitによってタスクの「どこかに」ディスパッチするために使用されます。一方、Taskクラスの関数はコンテキストを使用しませんよね?

したがって、たとえばTask.Run(...)は常にスレッドプールのワーカースレッドでアクションをディスパッチし、_SynchronizationContext.Current_を完全に無視します。 await Foobar()は、コンテキストを使用してawaitの後に生成されたタスクを実行しますか?

それが本当である場合、私の質問は次のとおりです。実際にアクションを実行するが、_SynchronizationContext.Current.Send/Post_を使用してディスパッチされるTaskを取得するにはどうすればよいですか?

そして、誰かがSynchronizationContextへの優れた導入を推奨できますか?特に、フレームワークの残りの部分でそれらがいつどのように使用されるのか? [〜#〜] msdn [〜#〜] はクラスについて非常に静かなようです。 Googleの上位ヒット( ここ および ここ )は、Windowsフォームのディスパッチのみに合わせて調整されているようです。 Stephen Clearyは 記事 を書いています。これは、どのようなコンテキストが存在し、どのように機能するかを知るのにうれしいですが、実際にどこでいつ使用されるかについては理解できません。

26
Imi

実際にアクションを実行するが、SynchronizationContext.Current.Send/Postを使用してディスパッチされるタスクを取得するにはどうすればよいですか?

特別なタスクスケジューラを使用する:

Task.Factory.StartNew(
    () => {}, // this will use current synchronization context
    CancellationToken.None, 
    TaskCreationOptions.None, 
    TaskScheduler.FromCurrentSynchronizationContext());

そして、誰でもSynchronizationContextの良い紹介をお勧めできますか

Stephen Clearyによる記事 It's All About the SynchronizationContext を見てください。

40
Dennis

これを学んでいるとき、TaskTPLによって使用されるTaskasync /によって使用されるものとはかなり異なることを指摘することが重要です。 awaitですが、同じタイプです。たとえば、TPLは通常親/子タスクを使用しますが、async/awaitは使用しません。

TPLはタスクスケジューラを使用してタスクを実行します。デニスが指摘したように、TaskScheduler.FromCurrentSynchronizationContextは、現在のPostSynchronizationContextを使用してタスクを実行するタスクスケジューラを提供します。

async/awaitは通常、タスクスケジューラを使用しません。紹介情報 async/await post がブログにあり、コンテキスト情報が含まれています MSDN記事 でも簡単に説明しています(ただし、見落としがちです)。基本的に、asyncメソッドがawaitで一時停止すると、デフォルトで現在のSynchronizationContextがキャプチャされます(nullでない限り、この場合、現在のTaskSchedulerをキャプチャします)。 asyncメソッドが再開すると、そのコンテキストでの実行が再開されます。

デニスは、現在のSynchronizationContextにタスクをスケジュールするTPLの方法を指摘しましたが、async/awaitの世界では、そのようなアプローチは必要ありません。むしろ、Task.Runを介してスレッドプールにタスクを明示的にスケジュールできます。

async Task MyMethodAsync()
{
  // Whee, on a SynchronizationContext here!
  await Task.Run(() => { }); // Ooo, on the thread pool!
  // Back on the SynchronizationContext ...
  //  ... automagically!
}

SynchronizationContextの記事を書いたのは、MSDNドキュメントが非常に不足していたためです。私は ブログの詳細情報 を持っていますが、重要なビットはすべてMSDNの記事にあります。多くのタイプは、AsyncOperationを直接使用するのではなく、SynchronizationContextを使用します。このための最良のドキュメントは EAPドキュメント(セクション「スレッド化とコンテキスト」)に埋め込まれています) です。ただし、async/awaitが原因でEAPが実質的に廃止されていることも指摘する必要があるため、AsyncOperation(またはSynchronizationContext)を使用してコードを記述しません。 -私が実際に自分で書くSynchronizationContextでない限り。

26
Stephen Cleary