我对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
的正确用法吗?如果不是什么可以替代?
答案 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。