C#多线程 - 限制并发线程的数量

时间:2011-08-10 14:39:31

标签: c# multithreading

我对控制我想要运行的并发线程数有疑问。让我解释一下我目前的做法:例如

 var myItems = getItems(); // is just some generic list

 // cycle through the mails, picking 10 at a time
 int index = 0;
 int itemsToTake = myItems.Count >= 10 ? 10 : myItems.Count;
 while (index < myItems.Count)
 {
     var itemRange = myItems.GetRange(index, itemsToTake);
     AutoResetEvent[] handles = new AutoResetEvent[itemsToTake];

     for (int i = 0; i < itemRange.Count; i++)
     {
         var item = itemRange[i];
         handles[i] = new AutoResetEvent(false);

         // set up the thread
         ThreadPool.QueueUserWorkItem(processItems, new Item_Thread(handles[i], item));
     }

    // wait for all the threads to finish
    WaitHandle.WaitAll(handles);

    // update the index
    index += itemsToTake;
    // make sure that the next batch of items to get is within range
    itemsToTake = (itemsToTake + index < myItems.Count) ? itemsToTake : myItems.Count -index;

这是我目前采用的路径。但是我根本不喜欢它。我知道我可以“管理”线程池本身,但我听说不建议这样做。那么替代方案是什么?信号量类?

感谢。

7 个答案:

答案 0 :(得分:4)

您可以考虑使用TPL或PLINQ,而不是直接使用ThreadPool。例如,使用PLINQ,您可以执行以下操作:

getItems().AsParallel()
          .WithDegreeOfParallelism(numberOfThreadsYouWant)
          .ForAll(item => process(item));

或使用Parallel

var options = new ParallelOptions {MaxDegreeOfParallelism = numberOfThreadsYouWant};
Parallel.ForEach(getItems, options, item => process(item));

确保指定并行度确实可以提高应用程序的性能。 TPL和PLINQ默认使用ThreadPool,它可以很好地管理正在运行的线程数。在.NET 4中,ThreadPool仅在可以提高性能的情况下实现添加更多处理线程的算法。

答案 1 :(得分:3)

不要使用THE treadpool,另外一个(只需查看谷歌,有六个实现)并自行管理。

管理the treadpool是不可取的,因为很多内部工作可能会进行,管理你的OWN线程池实例是完全可以的。

答案 2 :(得分:1)

看起来您可以使用ThreadPool.SetMaxThreads控制最大线程数,但我还没有测试过。

答案 3 :(得分:1)

假设问题是; “我如何限制工作线程的数量?”答案是使用生产者 - 消费者队列,您可以在其中控制工作线程的数量。只需排队您的物品并让它处理工人。

Here是您可以使用的通用实现。

答案 4 :(得分:0)

答案 5 :(得分:0)

documentation中,提到SetMaxThreads ...

public static bool SetMaxThreads (
int workerThreads,
int completionPortThreads
)
  

设置可以同时处于活动状态的线程池的请求数。高于该数字的所有请求将保持排队,直到线程池线程可用。

然而:

  

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

但我想通过使用非单例线程池可以更好地服务。

答案 6 :(得分:0)

没有理由处理混合线程同步构造(例如AutoResetEvent)和ThreadPool。

您可以使用一个可以作为协调器的类,负责异步执行所有代码。

使用任务或APM模式包裹“Item_Thread”执行的操作。然后使用Jeffrey Richter的 AsyncCoordinator 类(可以在CLR书中通过C#第3版的代码中找到)。