gpt4 book ai didi

c# - 链接 Task.WhenAll()

转载 作者:行者123 更新时间:2023-11-30 14:56:08 24 4
gpt4 key购买 nike

我想出了一些代码,将对 Task.WhenAll() 的多个调用链接在一起。我认为这可行,但它看起来有点滑稽。目的是让所有 Tasks 在关闭服务之前完成。省略一些循环、方法声明等的伪代码...

//initialize once on startup
Task _completion = Task.FromResult(0);

//Every minute a timer fires and we start some tasks
// and then chain them into the existing Task
var newTasks = Enumerable.Range(0, 10).Select(_ => Task.Factory.StartNew(() => {/* long running stuff here */})).ToArray();
_completion = Task.WhenAll(_completion, Task.WhenAll(newTasks));

//At some point a shutdown will be requested, and we can just wait for the one Task to complete
_completion.Wait();

出于某种原因,这是一个坏主意吗?我是否要最终持有对每个 Task 的引用,这样它们就永远无法被垃圾收集,或导致某些内部数组变得巨大,或其他一些可怕的事情?

我觉得重复从 Task.WhenAll() 中获取结果并将其反馈给 Task.WhenAll() 感觉有点奇怪。我看过source code for Task.WhenAll() ,而且我没有看到任何表明这可能是个问题的信息。但我当然不是这个话题的专家。

最佳答案

Am I going to end up holding a reference to every Task so they can never get garbage collected

Task.WhenAll 在所有任务完成时释放内存。这意味着任何给定的未完成任务都会导致内存被保存在同一个“批处理”中的所有其他任务中,每个批处理都“高于”它。如果您的批量大小特别大,并且完成所需的时间差异很大,那可能是个问题。如果您不是这种情况,那么您的代码应该没问题。

幸运的是,这个问题可以很容易地得到优化。您可以使用一个类,在该类中将每个事件任务添加到一组任务中,然后在每个任务完成时将其删除。然后,您可以轻松地等待每个当前事件 任务。这确保已完成的任务不会引用它们。这不仅意味着不要保留旧类的时间超过必要的时间,而且它将“保留所有事件任务”的逻辑分离到一个地方,从而简化了主应用程序中的逻辑。除了内存优化,它还可以提高代码的清晰度。

public class ActiveTaskTracker
{
private HashSet<Task> tasks = new HashSet<Task>();
public void Add(Task task)
{
if (!task.IsCompleted)//short circuit as an optimization
{
lock (tasks)
tasks.Add(task);
task.ContinueWith(t => { lock (tasks)tasks.Remove(task); });
}
}
public Task WaitAll()
{
lock (tasks)
return Task.WhenAll(tasks.ToArray());
}
}

关于c# - 链接 Task.WhenAll(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23685427/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com