スレッド作成に関しては、TPLとasync
/await
の違いを理解しようとしています。
TPL(TaskFactory.StartNew
)は、スレッドプール内のスレッドの作業をキューに入れるという点で、ThreadPool.QueueUserWorkItem
と同様に機能すると考えています。もちろん、新しいスレッドを作成するTaskCreationOptions.LongRunning
を使用しない限りです。
async
/await
は同様に機能するので、本質的には次のように考えました。
TPL:
Factory.StartNew( () => DoSomeAsyncWork() )
.ContinueWith(
(antecedent) => {
DoSomeWorkAfter();
},TaskScheduler.FromCurrentSynchronizationContext());
Async
/Await
:
await DoSomeAsyncWork();
DoSomeWorkAfter();
同じになります。私が読んでいたものから、それはasync
/await
のように思えます。それで、いつ新しいスレッドを作成し、いつ新しいスレッドを作成しませんか? IO完了ポートを扱っている場合、新しいスレッドを作成する必要がないことがわかりますが、そうでない場合は必要になると思います。FromCurrentSynchronizationContext
の私の理解は常に私はいつも本質的にUIスレッドだと思いました。
TPL(TaskFactory.Startnew)は、スレッドプール内のスレッドの作業をキューに入れるという点で、ThreadPool.QueueUserWorkItemと同様に機能すると考えています。
かなり 。
私が読んでいると、async/awaitのみが「時々」新しいスレッドを作成するようです。
実際、それは決してありません。マルチスレッドが必要な場合は、自分で実装する必要があります。 Task.Run
の短縮形である新しいTask.Factory.StartNew
メソッドがあり、これはおそらくスレッドプールでタスクを開始する最も一般的な方法です。
IO完了ポートを扱っている場合、新しいスレッドを作成する必要がないことがわかりますが、それ以外の場合は必要になると思います。
ビンゴ。したがって、Stream.ReadAsync
などのメソッドは、IOCPの周りにTask
ラッパーを実際に作成します(Stream
にIOCPがある場合)。
いくつかの非I/O、非CPU「タスク」を作成することもできます。簡単な例はTask.Delay
で、一定期間後に完了するタスクを返します。
async
/await
の素晴らしい点は、スレッドプール(たとえば、Task.Run
)にいくつかの作業をキューに入れ、I/Oにバインドされた操作(たとえば、Stream.ReadAsync
)を実行できることです。操作(例、Task.Delay
)...そしてそれらはすべてタスクです!それらは待つか、Task.WhenAll
のような組み合わせで使用できます。
Task
を返すメソッドはawait
edにすることができます-async
メソッドである必要はありません。したがって、Task.Delay
およびI/Oバインド操作はTaskCompletionSource
を使用してタスクを作成および完了します。スレッドプールで行われるのは、イベントが発生したときの実際のタスク完了(タイムアウト、I/O完了など) )。
FromCurrentSynchronizationContextの私の理解も常に少し曖昧だったと思います。私はいつも、本質的にUIスレッドだと考えていました。
SynchronizationContext
に 記事 を書きました。ほとんどの場合、SynchronizationContext.Current
:
すべてのスレッドcan独自のSynchronizationContext
を設定するため、上記のルールには例外があります。
デフォルトのTask
awaiterは、現在のasync
でSynchronizationContext
メソッドの残りをスケジュールすることに注意してくださいnullでない場合;それ以外の場合は、現在のTaskScheduler
に進みます。これは今日ではそれほど重要ではありませんが、近い将来、重要な区別になるでしょう。
私は自分のブログに async
/await
intro を書きました。最近、Stephen Toubが優れた async
/await
FAQを投稿しました 。
「並行性」対「マルチスレッド」については、 this related SO question 。を参照してください。async
は並行性を有効にします。 await Task.WhenAll
またはawait Task.WhenAny
を使用して並行処理を行うのは簡単です。また、スレッドプール(Task.Run
またはConfigureAwait(false)
など)を明示的に使用しない限り、同時に複数の並行操作を実行できます(たとえば、複数のI/OまたはDelay
などの他のタイプ-それらに必要なスレッドはありません。この種のシナリオでは「シングルスレッド同時実行」という用語を使用しますが、ASP.NETホストでは、実際には "zero-threaded concurrency"になります。
async/awaitは基本的にContinueWith
メソッドを簡素化します( Continuation Passing Style の継続)
それは並行性を導入しません-あなたはまだそれを自分でしなければなりません(またはフレームワークメソッドの非同期バージョンを使用します。)
したがって、C#5バージョンは次のようになります。
await Task.Run( () => DoSomeAsyncWork() );
DoSomeWorkAfter();