I/Oバウンドメソッド(DB呼び出しを行うメソッドなど)があるとします。このメソッドは、同期および非同期の両方で実行できます。あれは、
同期:
IOMethod()
非同期:
BeginIOMethod()
EndIOMethod()
次に、以下に示すようにさまざまな方法でメソッドを実行すると、リソース使用率に関するパフォーマンスの違いは何ですか?
var task = Task.Factory.StartNew(() => { IOMethod(); });
task.Wait();
var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
task.Wait();
_var task = Task.Factory.StartNew(() => { IOMethod(); });
task.Wait();
_
これにより、IOMethod()
の実行中にスレッドプールスレッドがブロックされ、Wait()
により現在のスレッドもブロックされます。ブロックされたスレッドの合計:2。
_var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
task.Wait();
_
これは(ほとんどの場合)スレッドを使用せずに非同期的に操作を実行しますが、Wait()
のために現在のスレッドをブロックします。ブロックされたスレッドの合計:1。
_IOMethod();
_
これは、IOMethod()
の実行中に現在のスレッドをブロックします。ブロックされたスレッドの合計:1。
現在のスレッドをブロックする必要がある場合、またはブロックしても問題ない場合は、TPLを使用しても実際には何も得られないため、これを使用する必要があります。
_var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
await task;
_
これにより、スレッドを使用せずに非同期で操作が実行されます。また、await
のおかげで、操作が非同期的に完了するまで待機します。ブロックされたスレッドの合計:0。
これは、非同期性を利用したい場合に使用すべきものであり、C#5.0を使用できます。
_var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
task.ContinueWith(() => /* rest of the method here */);
_
これにより、スレッドを使用せずに非同期で操作が実行されます。また、ContinueWith()
のおかげで、操作が非同期的に完了するまで待機します。ブロックされたスレッドの合計:0。
これは、非同期性を利用したいがC#5.0を使用できない場合に使用すべきものです。
(1).NETスレッドプールが(おそらく)Task
を処理します。
(2)BeginIOMethod
/EndIOMethod
ペアがネイティブに使用するメカニズムを使用して、非同期部分を処理します。非同期部分は.NETスレッドプールを含む場合と含まない場合があります。
たとえば、BeginIOMethod
がインターネット経由でTCPメッセージを送信しており、後で受信者が応答でTCPメッセージを送信する場合(受信した場合) EndIOMethod
)によって、操作の非同期的な性質は.NETスレッドプールによって提供されません。使用されているTCPライブラリは、非同期部分を提供しています。
これは TaskCompletionSource
class を使用して実現できます。 _Task.Factory.FromAsync
_は_TaskCompletionSource<T>
_を作成し、その_Task<T>
_を返し、EndIOMethod
をトリガーとして使用して、返された_Task<T>
_にResult
を配置できます。呼び出し時のフォーム_Task.Factory.FromAsync
_.
リソース使用率に関するパフォーマンスの違いは何ですか?
(1)と(2)の違いは、主に.NETスレッドプールにワークロードを追加するかどうかだけです。一般に、行うべき正しいことは、_Task.Factory.FromAsync
_/_Begin...
_のペアしか持っていない場合は_End...
_を選択し、それ以外の場合は_Task.Factory.StartNew
_を選択することです。
C#5.0を使用している場合は、task.Wait();
の代わりに非ブロッキング_await task;
_を使用する必要があります。 (svickの回答を参照してください。)