限制线程池中的线程数量

3

我在我的应用程序中使用了ThreadPool。我首先通过以下方式设置了线程池的限制:

ThreadPool.SetMaxThreads(m_iThreadPoolLimit,m_iThreadPoolLimit);
m_Events = new ManualResetEvent(false);

然后,我通过以下方式将作业排队:

WaitCallback objWcb = new WaitCallback(abc);
ThreadPool.QueueUserWorkItem(objWcb, m_objThreadData); 

这里的abc是我正在调用的函数名称。 之后,我要做以下操作,以便所有线程都汇聚到一个点上,主线程接管并继续执行。

m_Events.WaitOne();

我的线程限制是3。我面临的问题是,尽管线程池限制为3,但我的应用程序正在同时处理超过3个文件,而实际上它只应该一次处理3个文件。请帮我解决这个问题。


1
你应该检查SetMaxThreads()的返回值。 - Simone
4
如果你不知道自己在做什么,最好不要去调整线程池中的线程数。让运行时处理它。如果你需要限制同时访问的文件数量,请寻找更好的方法——比如使用信号量。 - Russell Troywest
微软不允许您将最大线程数设置为小于 CPU 核心数。我需要核心数减1个线程,留出1个核心给操作系统。 - Kostadin
4个回答

5

你使用的是什么类型的计算机?

来自MSDN

你不能将工作线程数或I/O完成线程数设置为小于计算机处理器数量的数字。

如果你有4个核心,则最小值为4。

还要注意:

如果公共语言运行时由Internet信息服务(IIS)或SQL Server等托管,主机可以限制或阻止对线程池大小的更改。

如果这是由IIS托管的网站,则你也无法更改线程池大小。


是的,我已经尝试将set max thread的一个参数设置为0,但仍然无法工作。 - Sanchaita Chakraborty
1
@Sanchaita 您不能将工作线程数设置为0。您必须将其设置为大于计算机处理器数量的数字(每个人至少有1个)。如果您有四核,则需要将其设置为至少4个。在我的I7上,Windows 7认为我有8个内核。数字至少为8。 - David Basarab

4
更好的解决方案涉及使用信号量Semaphore,它可以限制对资源的并发访问1。在您的情况下,该资源只是处理工作项的代码块。
var finished = new CountdownEvent(1); // Used to wait for the completion of all work items.
var throttle = new Semaphore(3, 3); // Used to throttle the processing of work items.
foreach (WorkItem item in workitems)
{
  finished.AddCount();
  WorkItem capture = item; // Needed to safely capture the loop variable.
  ThreadPool.QueueUserWorkItem(
    (state) =>
    {
      throttle.WaitOne();
      try
      {
        ProcessWorkItem(capture);
      }
      finally
      {
        throttle.Release();
        finished.Signal();
      }
    }, null);
}
finished.Signal();
finished.Wait();

在上面的代码中,WorkItem是一个假设的类,它封装了处理任务所需的特定参数。 任务并行库使这种模式更加容易。只需使用Parallel.ForEach方法,并指定限制并发的ParallelOptions.MaxDegreesOfParallelism即可。
var options = new ParallelOptions();
options.MaxDegreeOfParallelism = 3;
Parallel.ForEach(workitems, options,
  (item) =>
  {
    ProcessWorkItem(item);
  });

1我应该指出,我不喜欢使用Semaphore或任何阻塞设备来阻止ThreadPool线程。它基本上浪费了线程。您可能需要重新考虑整个设计。


2

你应该使用 Semaphore 对象来限制并发线程。


1
你说这些文件是打开的:它们是否正在被主动处理,还是只是保持打开状态?
如果你在让它们一直保持打开状态:我以前也犯过这个错误!依赖连接和资源(在我的情况下是一个数据库连接)在范围结束时自动关闭应该会起作用,但可能需要等到 dispose / 垃圾回收启动。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接