【问题标题】:Waking a thread in C#在 C# 中唤醒线程
【发布时间】:2011-10-06 22:26:01
【问题描述】:

我正在寻找一种简单的方法来让线程休眠并唤醒它。线程在后台无限循环运行,有时会做一些工作,有时只是运行。我发现 Sleep() 没有对应的 Wait() 并且使用 Interrupt() 唤醒线程会导致异常。显然,睡眠线程不应该被打扰。
因为我知道作品什么时候出现,所以告诉线程似乎是个好主意,而不是让它一遍又一遍地检查。

如何将线程置于“较轻的睡眠”状态,以便能够每秒单独唤醒或根据其他线程的命令唤醒?

//Thread to put to sleep and wake (thread1)
while (true)
{
    if (thereIsWork)
    { DoWork(); }
    //put thread to sleep in a way that other threads can wake it, and it wakes alone after some time (eg. 1000 ms)
    // Thread.Sleep(1000); //nice, but not working as desired
}

-

//Other thread:

thereIsWork = true;
//thread1.Wake(); //Not existing

【问题讨论】:

标签: c# multithreading thread-sleep


【解决方案1】:

您可以为此使用AutoResetEvent - 只需调用Set() 来表示需要完成的工作并让您的线程等待使用WaitOne() 调用它。

这意味着以这种方式进行通信的线程共享相同的 AutoResetEvent 实例 - 您可以将其作为执行实际工作的线程的依赖项传递。

【讨论】:

    【解决方案2】:

    线程不应该Sleep(),它应该在AutoResetEventManualResetEvent 上调用WaitOne(),直到其他线程在同一个resetevent 对象上调用Set()

    【讨论】:

      【解决方案3】:

      如何使用阻塞队列,以及 Monitor Pulse and Wait:

      class BlockingQueue<T>
      {
          private Queue<T> _queue = new Queue<T>();
          public void Enqueue(T data)
          {
              if (data == null) throw new ArgumentNullException("data");
              lock (_queue)
              {
                  _queue.Enqueue(data);
                  Monitor.Pulse(_queue);
              }
          }
          public T Dequeue()
          {
              lock (_queue)
              {
                  while (_queue.Count == 0) Monitor.Wait(_queue);
                  return _queue.Dequeue();
              }
          }
      }
      

      那么线程1就变成了

      BlockingQueue<Action> _workQueue = new BlockingQueue<Action>();
      
      while (true)
      {
          var workItem = _workQueue.Dequeue();
          workItem();
      }
      

      还有另一个线程:

      _workQueue.Enqueue(DoWork);
      

      注意:如果您使用 .Net 4 BlockingCollection 使用 Add and Take 而不是 Enqueue 和 Dequeue,则可能应该使用内置类型。

      编辑: 行。如果你想要它真的很简单......

      //Thread to put to sleep and wake (thread1)
      while (true)
      {
          lock(_lock)
          {
              while (!thereIsWork) Monitor.Wait(_lock);
              DoWork(); 
          }
          //put thread to sleep in a way that other threads can wake it, and it wakes alone after some time (eg. 1000 ms)
          // Thread.Sleep(1000); //nice, but not working as desired
      }
      

      //Other thread:
      lock(_lock)
      {
          thereIsWork = true;
          //thread1.Wake(); //Not existing
          Monitor.Pulse(_lock);
      }
      

      【讨论】:

      • 你想让它工作还是不工作?线程安全并不容易!如果您只使用内置的库集合,它看起来会不那么复杂。
      【解决方案4】:

      我不是线程专家,但也许 EventWaitHandle 是您正在寻找的。检查这个link

      【讨论】:

        猜你喜欢
        • 2011-08-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-01
        • 1970-01-01
        • 2011-07-29
        相关资源
        最近更新 更多