Task.Run增加IO绑定操作的并行性?

fre*_*ish 1 c# task-parallel-library async-await

我对此感到困惑,Task.Run并且我在互联网上阅读了所有内容.所以这是我的情况:我有一些处理传入套接字数据的函数:

public async Task Handle(Client client)
{
    while (true)
    {
        var data = await client.ReadAsync();
        await this.ProcessData(client, data);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是这有一个缺点,我只能在完成最后一个请求后再读取下一个请求.所以这是一个修改版本:

public async Task Handle(Client client)
{
    while (true)
    {
        var data = await client.ReadAsync();
        Task.Run(async () => {
            await this.ProcessData(client, data);
        });            
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个简化版本.对于更高级的,我当然会限制并行请求的最大数量.

无论如何,这ProcessData主要是IO绑定的(对dbs进行一些调用,处理非常轻松并将数据发回client)但我仍然继续阅读我应该使用Task.RunCPU绑定函数.

这是Task.Run我的情况的正确用法吗?如果不是什么可以替代?

Ste*_*ary 5

从概念上讲,这是一个很好的用法Task.Run.它与ASP.NET调度请求的方式非常相似:(异步)读取请求,然后将(同步或异步)工作分派给线程池.

实际上,您需要确保ProcessData正确处理结果.特别是,您需要观察异常.正如代码当前所代表的那样,任何异常ProcessData都将被吞噬,因为Task.Run没有观察到返回的任务.

IMO,处理每个消息错误最干净的方法是拥有自己的try/ catch,如下:

public async Task Handle(Client client)
{
  while (true)
  {
    var data = await client.ReadAsync();
    Task.Run(async () => {
      try { await this.ProcessData(client, data); }
      catch (Exception ex) {
        // TODO: handle
      }
    });            
  }
}
Run Code Online (Sandbox Code Playgroud)

其中// TODO: handle是适合您的应用程序的错误处理代码.例如,您可能会在套接字上发送错误响应,或者只是log-and-ignore.