2011-02-16 139 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