在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());

我有一些问题:

  1. 如果列表中有10,000个用户,它是否会同时创建10,000个任务(巨大的内存峰值)?或者它只是创建,比如说10个任务,然后当一些任务完成时,其他任务就会被启动?
  2. 我是如何使用取消令牌看起来正确吗?
  3. 如果我在调用它之后立即取消操作,它是否仍然需要在取消之前启动所有10,000个任务,或者因为我将取消令牌传递给Task而避免这种情况。运行参数?
在我的测试中,它似乎工作得很好。我只是想确保我没有忽略任何事情,或者我可能会遇到一些问题,或者是否有我没有遵循的最佳实践。 我愿意接受任何建议。提前谢谢。

更新

根据评论,我对外部服务或其数据库没有任何控制。我只有他们提供给我的呼叫,这需要一个用户。谢谢。

在c#中启动数千个任务的最佳方式是什么?

是的,这段代码将立即启动所有操作。Task.Run的作用不大。由于这是使用异步IO,线程池几乎没有参与。它不会限制这个

不要这样做。这可能会使某些资源过载。使用来自https://blogs.msdn.microsoft.com/pfxteam/2012/03/05/implementing-a-simple-foreachasync-part-2/的最后一段代码。这样的事情应该在框架中,因为几乎总是有必要为IO工作选择一个精确的并行度。

修复后

(3)不重要。在修复之前,令牌几乎没有影响,因为所有操作都立即开始,导致令牌只立即检查一次。之后就不能取消了。

您还可以将令牌传递给UpdateUserInExternalService以实现更直接的取消。