当有工作要做时挂起并通知线程

本文关键字:挂起 通知 线程 工作 | 更新日期: 2023-09-27 17:47:47

我有多个线程(运行在IIS上的C#应用程序)在运行,它们都需要与同一MQ后端通信。为了最大限度地减少网络流量,我只需要在有工作要做时发送后端请求。如果有工作要做,将有一个线程要监视,它需要通知其他线程它们也应该开始处理。当前的解决方案包括监视器线程设置一个全局变量,并让其他线程循环并检查,即在监视器线程中:

CheckIfWorkAvailable() {
  while(true) {
    if (queue.Empty != true) {
      workToBeDone = true;
    }
  }//end while loop
}

然后在工作线程中:

DoWork() {
  while(true) {
    if (workToBeDone == true) {
      //do work...
    }
    else {
      Thread.Sleep(x seconds)
    }
  }//end while loop
}

监视线程是否可以在有工作要做时通知工作线程,而不是让它们循环并休眠?工作线程还设置了一个计数器,指示它们正在工作,并在工作完成时递减,这样workToBeDone标志就可以设置为false。

当有工作要做时挂起并通知线程

查看WaitHandle及其降序。EventWaitHandle可能适合您的需求。

与Kent指出的WaitHandle类一样,简单的Monitor.Wait和Monitor.Pulse/PulseAll可以轻松做到这一点。它们比事件句柄"更轻",尽管在某种程度上更原始。(你不能在多个显示器上等待,等等)

在我的线程文章中,我有一个这样的例子(作为生产者-消费者队列)。

在您的场景中,也可以直接使用ThreadPool类。这意味着你不需要设置你将要使用的线程,它还允许你根据要完成的工作来设置线程。

如果你想在项目中使用CTP,你可能想看看TPL,因为它有一些更高级的同步和任务处理功能。

对于希望所有工作线程在满足状态时继续的情况,请使用ManualResetEvent(看起来像您在这里想要的)。在每次某些工作可用时只想向单个工作人员发出信号的情况下,请使用AutoResetEvent。当您希望允许特定数量的线程继续时,请使用Semaphore。对于这种类型的事情,几乎从不使用全局变量,如果使用了,请将其标记为volatile。

在这种情况下要小心。你不想导致"锁车队"的发生,因为每次发布一件物品时,你都会释放所有的工人,让他们同时进入队列,但却不得不再次等待。

http://msdn.microsoft.com/en-us/library/yy12yx1f(VS.80).aspx

您可以使用自动重置事件