.NET如何按特定ID增加/减少线程数



.NET Framework 4.5.2。我正在尝试更新一些旧代码,并试图找出如何管理特定ID的运行线程数。这就是代码。

foreach (ThreadGroup thread_group in threadGroups)
{
if (ImportQueues.TryGetValue(thread_group.ThreadGroupID, out BlockingCollection<ImportFrequency> configuration))
{
if (configuration.Count > thread_group.ThreadCount)
{
// increase number of threads running for this group
}
else if (configuration.Count < thread_group.ThreadCount)
{
// decrease number of threads running for this group
}
}
else // Spin up the initial threads
{
ImportQueues.Add(thread_group.ThreadGroupID, new BlockingCollection<ImportFrequency>());
for (int x = 0; x < thread_group.ThreadCount; x++)
{
Thread import_thread = new Thread(new ParameterizedThreadStart(ProcessImportQueue)) { IsBackground = true };
import_thread.Start((ImportQueues[thread_group.ThreadGroupID]));
}
}
}

本质上,我们为每个组的阻塞集合运行thread_group.ThreadCount数量的线程,这些线程将不断更新。另外,thread_group可以被更新以改变ThreadCount。如果更改增加了线程数,请进一步旋转以处理阻塞集合。如果减少,请等待线程数的差异结束,而其他线程则继续运行。

这在这种范式下可能吗?还是我需要找到一种更好的方法来管理线程?

编辑:我尝试过的一个解决方案是使用CancellationTokens。当我启动一个线程时,我会传入一个包含上下文和CancellationToken的模型。该模型将保存到全局变量中。如果我们需要减少线程数量,我会检查需要停止的线程数量,并取消令牌,这会停止该线程的无限循环并停止它。

正如我所理解的示例代码,它创建了N个队列,每个队列由M个线程处理。

这有一些潜在的问题。我说,由于存在,可能有一些特殊情况推动了这样的解决方案,但斯特金的法律表明,这可能只是一种误导性的尝试,目的是实现一些不明确的目标。

  1. 很可能N*M大于可用硬件线程的数量,导致空闲线程消耗资源,或者在加载所有线程的情况下进行不必要的上下文切换
  2. 目前尚不清楚排队的队伍是否有任何不同。如果它们是相同的,为什么不使用单个队列呢
  3. 虽然添加线程相当简单,但减少线程可能有点复杂。线程应该只协同取消,所以您需要某种方式来发出应该取消线程的信号。但是,如果线程在等待队列中的项目时被阻止,您可能会遇到这样的情况:您已经要求线程停止,但他们还没有停止,而且您启动线程的速度比实际释放线程的速度快,最终线程会用完。这可能是可以解决的,但目前的解决方案是否能做到这一点尚不清楚
  4. "导入"听起来像是涉及IO的东西,而且IO通常不会很好地随线程数量而扩展。在最坏的情况下,并行IO甚至会损害性能
  5. 目前尚不清楚实际的处理过程在做什么。根据我的经验,如果使用得当,cpu核心可以做大量的工作。当事情进展缓慢时,通常意味着代码正在做一些不必要的工作。一些初级程序员通过尝试将多线程作为第一步和最后一步来处理性能问题。在分析代码和提高效率时,通常可以提供更大的改进

对于需要并行处理的队列的简单情况,我会考虑使用并行。Foreach在阻塞集合上循环,使用parallelExtensionExtras可以获得更好的分区器。这应该会自动尝试平衡用于可用硬件的线程数量和CPU使用模式,以获得最大吞吐量。

但是,如果没有很好地理解它试图做什么,以及为什么应该把它改成更好的东西,我就不会接触工作代码。任何最好只有在充分的自动化测试到位后,以帮助避免引入新的错误。因为代码太旧而只更改是一个糟糕的想法。

最新更新