【问题标题】:Limiting the number of threadpool threads限制线程池线程的数量
【发布时间】:2011-05-16 13:09:24
【问题描述】:

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

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

然后我使用以下命令将作业排队

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

这里 abc 是我正在调用的函数的名称。 在此之后,我正在执行以下操作,以便我的所有线程都达到 1 点,并且主线程接管并继续进一步

m_Events.WaitOne();

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

【问题讨论】:

  • 你应该检查SetMaxThreads()的返回值。
  • 除非您知道自己在做什么,否则最好不要乱搞线程池中的线程数。让运行时处理它。如果您需要限制同时访问的文件数量,请找到更好的方法 - 例如使用信号量。
  • Microsoft 不允许您设置最大线程数

标签: c# .net multithreading threadpool


【解决方案1】:

你用的是什么电脑?

来自MSDN

你不能设置工人的数量 线程或 I/O 的数量 完成线程数更小 比处理器的数量 电脑。

如果您有 4 个核心,那么您可以拥有的最小核心是 4 个。

另请注意:

如果公共语言运行时是 托管,例如通过 Internet 信息服务 (IIS) 或 SQL 服务器,主机可以限制或阻止 更改线程池大小。

如果这是一个由 IIS 托管的网站,那么您也无法更改线程池大小。

【讨论】:

  • 是的,我已经尝试将 set max thread 的 1 个参数设置为 0,但仍然无法正常工作。
  • @Sanchaita 您不能将工作线程数设置为 0。您必须将其设置为大于计算机处理器数的数字(每个人至少有 1 个)。如果您有四核,那么您需要将其设置为至少 4。在我的 I7 Windows 7 上,我认为我有 8 个核心。该数字必须至少为 8 个。
【解决方案2】:

更好的解决方案是使用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 是一个假设的类,它封装了处理您的任务所需的特定参数。

Task Parallel Library 使这种模式更容易。只需使用Parallel.ForEach 方法并指定一个ParallelOptions.MaxDegreesOfParallelism 来限制并发。

var options = new ParallelOptions();
options.MaxDegreeOfParallelism = 3;
Parallel.ForEach(workitems, options,
  (item) =>
  {
    ProcessWorkItem(item);
  });

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      您说文件是打开的:它们实际上是在积极处理,还是只是保持打开状态? 如果你让它们打开:去过那里,做到了!依靠连接和资源(在我的情况下是数据库连接)在范围结束时关闭应该可以工作,但可能需要处理/垃圾收集才能启动。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-14
        • 1970-01-01
        • 1970-01-01
        • 2019-01-29
        相关资源
        最近更新 更多