Task.Run 增加 IO 绑定操作的并行性?
Task.Run to increase parallelism of IO-bound operations?
我对 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
的用法是否正确?如果不是,还有什么替代方案?
从概念上讲,这是 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
是适合您的应用程序的错误处理代码。例如,您可能会在套接字上发送错误响应,或者只是记录并忽略。
我对 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
的用法是否正确?如果不是,还有什么替代方案?
从概念上讲,这是 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
是适合您的应用程序的错误处理代码。例如,您可能会在套接字上发送错误响应,或者只是记录并忽略。