在C#中唤醒一个线程

时间:2011-10-06 22:26:01

标签: c# multithreading thread-sleep

我正在寻找一种简单的方法来让一个线程进入睡眠并唤醒它。线程在无限循环中在后台运行,有时会做一些工作,有时只是运行。我发现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

4 个答案:

答案 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