gpt4 book ai didi

c# - N 个线程异步获取/执行任务

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

我在某处的数据库队列中有无限数量的任务。让程序在 n 个不同线程上同时处理 n 个任务,并在旧任务完成时启动新任务的最佳方法是什么?当一个任务完成时,另一个任务应该异步开始。当前运行的计数应始终为 n。

我最初的想法是使用线程池,但考虑到要处理的任务将在各个线程中检索,这似乎没有必要。换句话说,每个线程将自己去获取下一个任务,而不是让主线程获取任务然后分发它们。

我看到了执行此操作的多个选项,但我不知道应该使用哪个来获得最佳性能。

1) 线程池 - 鉴于不一定有任何等待线程,我不确定这是必要的。

2) 信号量 - 与 1 相同。如果没有任务等待主线程分配,信号量有什么好处?

3) 永远相同的线程 - 用 n 个线程启动程序。当一个线程完成工作时,它自己获得下一个任务。主线程只是进行监控以确保 n 个线程仍处于事件状态。

4) 事件处理 - 与 3 相同,除了当线程完成任务时,它会在死亡前触发 ImFinished 事件。 ImFinished 事件处理程序启动一个新线程。这看起来就像 3,但开销更大(因为不断创建新线程)

5) 还有别的吗?

最佳答案

BlockingCollection使整个事情变得微不足道:

var queue = new BlockingCollection<Action>();

int numWorkers = 5;

for (int i = 0; i < numWorkers; i++)
{
Thread t = new Thread(() =>
{
foreach (var action in queue.GetConsumingEnumerable())
{
action();
}
});
t.Start();
}

然后您可以让主线程在启动 worker 之后(或之前,如果需要)将项目添加到阻塞集合。您甚至可以生成多个生产者线程以将项目添加到队列中。

请注意,更传统的方法是使用 Tasks 而不是直接使用 Thread 类。我没有首先建议它的主要原因是您明确要求要运行的线程的确切数量(而不是最大数量)并且您对 Task 的方式没有那么多的控制权运行对象(这很好;它们可以代表您进行优化)。如果该控制不如您所说的那么重要,则以下可能最终会更可取:

var queue = new BlockingCollection<Action>();

int numWorkers = 5;

for (int i = 0; i < numWorkers; i++)
{
Task.Factory.StartNew(() =>
{
foreach (var action in queue.GetConsumingEnumerable())
{
action();
}
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}

关于c# - N 个线程异步获取/执行任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13568994/

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