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

时间:2018-01-24 15:39:46

标签: c# async-await task-parallel-library

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

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

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

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

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

无论如何,这个ProcessData主要是IO绑定的(对dbs进行一些调用,处理非常轻松并将数据发送回client)但我一直在读,我应该使用Task.Run CPU限制功能。

对我的案例来说,这是Task.Run的正确用法吗?如果不是什么可以替代?

1 个答案:

答案 0 :(得分: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
      }
    });            
  }
}

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