2011-02-16 135 views
19

我想知道在使用TPL TaskFactory.FromAsync和使用TaskFactory.StartNew阻塞版本的方法之間是否有任何性能影響。我正在寫一個支持不超過100個併發連接的TCP服務器。在用第一個選項&編寫代碼之後,連續多次讀取&寫入操作,結果我留下了難看,難以調試的代碼。TPL TaskFactory.FromAsync vs帶阻塞方法的任務

我相信用同步版本&編寫代碼,然後用Task包裝它會降低複雜性&增加可測試性,但是我擔心這樣做的性能影響。

例如,是否有這兩個電話之間的性能差異:

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)); 

回答

45

絕對要使用FromAsync當API提供的BeginXXX/EndXXX版本的方法。不同之處在於,在類似於StreamSocketWebRequest的情況下,實際上最終會在封面下面使用異步I/O(例如,Windows上的I/O完成端口),這比阻止多個CPU線程正在進行同步操作。這些方法提供了實現I/O可伸縮性的最佳方式。

查看MSDN上名爲TPL and Traditional .NET Asynchronous Programming的.NET SDK的這一部分,瞭解如何結合這兩種編程模型實現異步涅。的更多信息。

+1

你有這不能不調用Web方法的任何資源(例如)使用Begin/End和Async比使用Async同步版更好?你說什麼是有道理的,我只是喜歡在官方的地方閱讀它。 – 2012-06-27 12:36:50

5

繼從外部鏈接的副本:

是。在.NET 4中,任務並行庫包含用於APM模式(開始/結束)的內置包裝 :Task.Factory.FromAsync。例如, 如果你想創建一個以流的 的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); 

Under the covers, FromAsync is just built on top of TaskCompletionSource<TResult>. A simple version of FromAsync for this read example would look something like: 

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/ed8a14e8-d19a-42d1-bc3f-7017bdfed09c

+3

請提供外部鏈接的內容。否則,如果鏈路斷開,你的答案是毫無價值的。 – sra 2011-12-29 09:52:09