我对 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 绑定(bind)的(对 dbs 进行一些调用,非常轻的处理并将数据发送回 client
),但我一直在阅读我应该使用的内容Task.Run
具有 CPU 绑定(bind)函数。
Task.Run
是否适合我的情况?如果不是,还有什么替代方案?
最佳答案
从概念上讲,这是 Task.Run
的一个很好的用法。它与 ASP.NET 分派(dispatch)请求的方式非常相似:(异步)读取请求,然后分派(dispatch)(同步或异步)工作到线程池。
在实践中,您需要确保正确处理 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
是适合您的应用程序的错误处理代码。例如,您可能会在套接字上发送错误响应,或者只是记录并忽略。
关于c# - Task.Run 以增加 IO 绑定(bind)操作的并行性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48426265/