在c#中启动数千个任务的最佳方式是什么?
本文关键字:任务 千个 最佳 方式 是什么 启动 | 更新日期: 2023-09-27 18:13:19
假设我有一个List
用户,我想对他们所有人执行一些操作,比如更新他们在数据库中的一个属性。用户列表可能包含数万或数十万个用户。如果要对用户完成的所有工作都在我的机器上,那么我将只使用Parallel.ForEach
来处理它们,但是因为这将涉及到等待(可能是许多秒)对外部服务的调用来完成,我认为使用Task
s更合适。
现在,这是我的代码:
Task.WaitAll(usersList.Select(user => Task.Run(() => async
{
cancellationToken.ThrowIfCancellationRequested();
try
{
await UpdateUserInExternalService(user);
}
catch (Exception ex)
{
LogError($"Something went wrong with user 'user.Username'.", ex);
}
}, cancellationToken)).ToArray());
我有一些问题:
- 如果列表中有10,000个用户,它是否会同时创建10,000个任务(巨大的内存峰值)?或者它只是创建,比如说10个任务,然后当一些任务完成时,其他任务就会被启动?
- 我是如何使用取消令牌看起来正确吗?
- 如果我在调用它之后立即取消操作,它是否仍然需要在取消之前启动所有10,000个任务,或者因为我将取消令牌传递给Task而避免这种情况。运行参数?
根据评论,我对外部服务或其数据库没有任何控制。我只有他们提供给我的呼叫,这需要一个用户。谢谢。
是的,这段代码将立即启动所有操作。Task.Run
的作用不大。由于这是使用异步IO,线程池几乎没有参与。它不会限制这个
不要这样做。这可能会使某些资源过载。使用来自https://blogs.msdn.microsoft.com/pfxteam/2012/03/05/implementing-a-simple-foreachasync-part-2/的最后一段代码。这样的事情应该在框架中,因为几乎总是有必要为IO工作选择一个精确的并行度。
修复后(3)不重要。在修复之前,令牌几乎没有影响,因为所有操作都立即开始,导致令牌只立即检查一次。之后就不能取消了。
您还可以将令牌传递给UpdateUserInExternalService
以实现更直接的取消。