唤醒C#中的线程

本文关键字:线程 唤醒 | 更新日期: 2023-09-27 18:10:42

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

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

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

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

使用具有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);

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

编辑:好的。如果你想要非常简单的。。。

//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);
}

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