You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Task.WhenEach时向任务列表追加任务是否安全?相关实现疑问

问题解答

循环内新增的Task不会被Task.WhenEach捕获

Task.WhenEach在调用时会基于传入的任务集合生成一个固定的异步枚举器,它只会跟踪调用瞬间集合里的任务。后续你向tasks列表添加的新任务,不会被这个已经初始化的枚举器识别,自然不会被处理。

正确的实现方式(含限流)

你补充的基于SemaphoreSlim限流+Task.WhenAny循环的写法是完全可行的,能动态处理新增任务,逻辑清晰且能控制并发量。完整代码如下:

var tasks = new List<Task<List<int>>>();
var semaphore = new SemaphoreSlim(2);
await semaphore.WaitAsync();
tasks.Add(MyTask(semaphore, 0));
while (tasks.Any())
{
    var completedTask = await Task.WhenAny(tasks);
    tasks.Remove(completedTask);
    var data = await completedTask;
    foreach (var i in data)
    {
        await semaphore.WaitAsync();
        tasks.Add(MyTask(semaphore, i));
    }
}

Console.WriteLine("Exiting");

async Task<List<int>> MyTask(SemaphoreSlim semaphoreSlim, int i)
{
    await Task.Delay(3000);
    semaphoreSlim.Release();
    return [i+1, i+2];
}

性能优化建议

如果需要处理大量任务,List<Task>的Remove操作是O(n)复杂度,可能影响性能。可以改用ConcurrentQueue<Task<List<int>>>存储任务,配合队列操作替代Remove,提升效率:

var taskQueue = new ConcurrentQueue<Task<List<int>>>();
var semaphore = new SemaphoreSlim(2);
await semaphore.WaitAsync();
taskQueue.Enqueue(MyTask(semaphore, 0));

while (!taskQueue.IsEmpty)
{
    var completedTask = await Task.WhenAny(taskQueue);
    // 从队列中移除已完成的任务,保留未完成的任务
    var tempTasks = new List<Task<List<int>>>();
    while (taskQueue.TryDequeue(out var task))
    {
        if (task != completedTask)
            tempTasks.Add(task);
    }
    foreach (var task in tempTasks)
    {
        taskQueue.Enqueue(task);
    }

    var data = await completedTask;
    foreach (var i in data)
    {
        await semaphore.WaitAsync();
        taskQueue.Enqueue(MyTask(semaphore, i));
    }
}

Console.WriteLine("Exiting");

async Task<List<int>> MyTask(SemaphoreSlim semaphoreSlim, int i)
{
    await Task.Delay(3000);
    semaphoreSlim.Release();
    return [i+1, i+2];
}

内容的提问来源于stack exchange,提问作者schgab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 01:11:14