我正在寻找一种简单的方法来让一个线程进入睡眠并唤醒它。线程在无限循环中在后台运行,有时会做一些工作,有时只是运行。我发现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
答案 0 :(得分:4)
线程不应该Sleep()
,它应该在WaitOne()
或AutoResetEvent
上调用ManualResetEvent
,直到某个其他线程在同一个resetevent对象上调用Set()
答案 1 :(得分:4)
您可以使用AutoResetEvent
来调用Set()
来表示需要完成的工作,并让您的线程等待使用WaitOne()
调用它。
这意味着以这种方式通信的线程共享相同的AutoResetEvent
实例 - 您可以将其作为执行实际工作的线程的依赖项传递。
答案 2 :(得分:1)
如何使用阻塞队列,使用Monitor Pulse和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);
}
答案 3 :(得分:0)
我不是线程专家,但也许你正在寻找EventWaitHandle。请检查此link