代码之家  ›  专栏  ›  技术社区  ›  recursive

如何完成threadpool.join?

  •  5
  • recursive  · 技术社区  · 14 年前

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

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

    2 回复  |  直到 14 年前
        1
  •  8
  •   Kieren Johnstone    14 年前

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

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

    这是一个黑客,但我不知道如何将其简化为任何简单的东西!


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

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

        2
  •  3
  •   Brian Gideon    14 年前

    执行此操作的标准模式是使用一个计数器,该计数器保存挂起的工作项和一个 ManualResetEvent 当计数器达到零时发出信号。这通常比使用 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();