20

TaskFactory.FromAsync我想知道使用 TPL和使用TaskFactory.StartNew方法的阻塞版本之间是否有任何性能影响。我正在编写一个支持不超过 100 个并发连接的 TCP 服务器。在使用第一个选项编写代码并使用 continue with 链接多个读写操作之后,我留下了丑陋、难以调试的代码。

我相信用同步版本编写代码然后用任务包装它会降低复杂性并增加可测试性,但我担心这样做会影响性能。

例如,这两个调用之间是否存在任何性能差异:

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不同之处在于,在Streamor Socketor之类的情况下WebRequest,您实际上最终会在底层使用异步 I/O(例如 Windows 上的 I/O 完成端口),这比阻塞多个 CPU 线程执行同步操作。这些方法提供了实现 I/O 可伸缩性的最佳方式。

查看 MSDN 上名为TPL 和传统 .NET 异步编程的 .NET SDK 部分,了解有关如何结合这两种编程模型以实现异步必杀技的更多信息。

于 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 回答