Multithreading 如何实现线程池。加入?

Multithreading 如何实现线程池。加入?,multithreading,.net-3.5,windows-services,threadpool,Multithreading,.net 3.5,Windows Services,Threadpool,我正在编写一个使用ThreadPool.QueueUserWorkItem()的windows服务。每个线程都是一个短期任务 当服务停止时,我需要确保当前正在执行的所有线程都已完成。是否有某种方法等待队列自行清除?您可以在每个线程中创建一个事件(例如,ManualResetEvent),并将其保存在一个同步列表中(使用lock构造)。设置事件或在任务完成时将其从列表中删除 当您想要加入时,可以使用WaitHandle.WaitAll()等待所有事件发出信号 这是一个黑客,但我看不出如何将它简化为

我正在编写一个使用
ThreadPool.QueueUserWorkItem()
的windows服务。每个线程都是一个短期任务

当服务停止时,我需要确保当前正在执行的所有线程都已完成。是否有某种方法等待队列自行清除?

您可以在每个线程中创建一个事件(例如,
ManualResetEvent
),并将其保存在一个同步列表中(使用
lock
构造)。设置事件或在任务完成时将其从列表中删除

当您想要加入时,可以使用
WaitHandle.WaitAll
()等待所有事件发出信号

这是一个黑客,但我看不出如何将它简化为更简单的东西


编辑:另外,您可以确保没有发布新事件,然后等待几秒钟。如果它们确实是短暂的,你就没有问题了。更简单,但更粗糙


最后,如果只是很短的时间,服务将不会退出,直到所有线程都死掉(除非它们是后台线程);因此,根据我的经验,如果时间很短,维修控制经理一秒钟左右都不会介意,你可以让它们过期。

这样做的标准模式是使用一个计数器,它保存挂起的工作项的数量,以及一个当计数器达到零时发出信号的
ManualResetEvent
。这通常比为每个工作项使用
WaitHandle
要好,因为当同时有很多工作项时,它的伸缩性不太好。另外,一些静态的
WaitHandle
方法只接受最多64个实例

// Initialize to 1 because we are going to treat the current thread as
// a work item as well. This is to avoid a race that could occur when
// one work item gets queued and completed before the next work item
// is queued.
int count = 1;
var finished = new ManualResetEvent(false); 
try 
{ 
  while (...)
  {  
    Interlocked.Increment(ref counter);
    ThreadPool.QueueUserWorkItem( 
      delegate(object state) 
      { 
        try 
        { 
          // Your task goes here. 
        } 
        finally 
        { 
          // Decrement the counter to indicate the work item is done.
          if (Interlocked.Decrement(ref count) == 0) 
          { 
            finished.Set(); 
          } 
        } 
      }); 
  } 
}
finally
{
  // Decrement the counter to indicate the queueing thread is done.
  if (Interlocked.Decrement(ref count) == 0) 
  { 
    finished.Set(); 
  } 
}
finished.WaitOne(); 

它们应该是短期的,但对于我的用例,我需要比“应该工作”更多的保证。我正在考虑使用一个互锁线程计数器来跟踪池中的线程数,并等待线程数等于零。实际上,我更喜欢你的第一个建议而不是计数器。