1

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

4 回答 4

4

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

于 2011-10-06T22:28:27.833 回答
4

您可以AutoResetEvent为此使用 - 只需调用Set()需要完成的信号工作并让您的线程等待使用WaitOne().

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

于 2011-10-06T22:28:56.293 回答
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 和 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);
}
于 2011-10-06T23:50:09.857 回答
0

我不是线程专家,但也许 EventWaitHandle 是您正在寻找的。检查此链接

于 2011-10-06T22:48:45.370 回答