20

TaskFactory.FromAsyncTPLを使用TaskFactory.StartNewすることと、メソッドのブロックバージョンを使用することの間にパフォーマンスへの影響があるかどうか疑問に思いました。100以下の同時接続をサポートするTCPサーバーを作成しています。最初のオプションでコードを記述し、続行を使用して複数の読み取りおよび書き込み操作を連鎖させた後、私は醜い、デバッグが難しいコードを残されました。

同期バージョンでコードを記述し、それをタスクでラップすると、複雑さが軽減され、テスト容易性が向上すると思いますが、これを行うことによるパフォーマンスへの影響が心配です。

たとえば、これら2つの呼び出しの間にパフォーマンスの違いはありますか。

NetworkStream stream;
byte[] data;
int bytesRead;

//using FromAsync
Task<int> readChunk = Task<int>.Factory.FromAsync (
      stream.BeginRead, stream.EndRead,
      data, bytesRead, data.Length - bytesRead, null);

//using StartNew with blocking version
Task<int> readChunk2 = Task<int>.Factory.StartNew(() => 
      stream.Read(data, bytesRead, data.Length - bytesRead));
4

2 に答える 2

45

APIがメソッドのBeginXXX/EndXXXバージョンを提供するときに絶対に使用したいと思います。違いは、またはFromAsyncのようなものの場合、実際にはカバーの下で非同期I / Oを使用することになります(たとえば、WindowsのI / O完了ポート)。これは、複数のCPUスレッドをブロックするよりもはるかに効率的です。同期操作。これらの方法は、I/Oスケーラビリティを実現するための最良の方法を提供します。StreamSocketWebRequest

これら2つのプログラミングモデルを組み合わせて非同期ニルヴァーナを実現する方法の詳細については、MSDNの.NETSDKの「TPLおよび従来の.NET非同期プログラミング」というタイトルのセクションを確認してください。

于 2011-02-22T03:54:47.110 に答える
5

外部リンクからのコピーをたどる:

はい。.NET 4では、タスク並列ライブラリにAPMパターン(開始/終了)の組み込みラッパーTask.Factory.FromAsyncが含まれています。たとえば、StreamのBeginRead / EndReadメソッドを呼び出すためのタスクを作成する場合は、次のように実行できます。

Stream s = ...;
byte [] buffer = ...;
Task<int> numBytesRead = Task<int>.Factory.FromAsync(s.BeginRead, s.EndRead, buffer, 0, buffer.Length, null);
// or with await
int numBytesRead = await Task<int>.Factory.FromAsync(s.BeginRead, s.EndRead, buffer, 0, buffer.Length, null);

裏では、FromAsyncはTaskCompletionSourceの上に構築されています。この読み取り例のFromAsyncの単純なバージョンは、次のようになります。

var tcs = new TaskCompletionSource<TResult>();
s.BeginRead(buffer, 0, buffer.Length, iar =>
{
    try { tcs.SetResult(s.EndRead(iar)); }
    catch(Exception exc) { tcs.SetException(exc); }
}, null);
Task<int> numBytesRead = tcs.Task;

http://social.msdn.microsoft.com/Forums/en/async/thread/ed8a14​​e8-d19a-42d1-bc3f-7017bdfed09c

于 2011-04-29T15:59:43.157 に答える