【发布时间】:2022-03-10 05:14:02
【问题描述】:
.NET 框架 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。该模型被保存到一个全局变量中。如果我们需要减少线程的数量,我会经历许多需要停止并取消令牌,这会停止该线程的无限循环并停止它。
【问题讨论】:
-
一般建议使用线程池而不是手动启动线程。您是否评估过您的解决方案,以确认它确实比更简单的解决方案带来了任何改进?以我的经验,通常有空间更有效地做事,而不是在问题上抛出线程,
-
您发布的代码是您未描述的问题的当前解决方案。我们可以建议使用更惯用的方式来执行此操作(即线程池),但在不知道此代码解决的实际问题的情况下,我们无法轻易为您提供一个好的具体解决方案。
-
让我换一种说法。有一个问题X,这个解决方案Y被实施了。您来到这里并清楚地阐明了 Y 是什么以及它的作用。你问我们有没有更好的方法来做 Y。很可能有更好的方法来做 X。如果你能添加 X 的细节并让我们解决这个问题,那就太好了。我怀疑“高层管理人员”会被你的聪明才智所震撼,他们会感激你的改变。
-
@Carspn - 您能否在不提及线程的情况下描述您要处理的内容?我想知道业务问题是什么,而不是您为它设计的解决方案。我想了解您正在尝试做什么,以便我可以决定线程、任务或其他解决方案是否是最好的。
-
@Carspn - 谢谢。我们越来越近了。所以
while (true) var x = collection.Take();模式有点讨厌。您正在处理一个可能不会做任何工作的线程。线程持有至少 1MB 内存只是为了存在。你想让它们一直工作(即不等待)。如果他们没有工作,他们应该被解雇。我认为这里有很大的空间可以让你的代码在不需要任何线程代码的情况下更快地工作。你能显示完整的代码吗?
标签: c# .net multithreading