简体   繁体   中英

Waking a thread in C#

I am looking for a simple way to put a thread to sleep and to wake it. The thread runs in background in an infinite loop and sometimes does some work, sometimes just runs through. I have found out that there is no corresponding Wait() to the Sleep() and waking a thread with Interrupt() causes an exception. Apparently a sleeping thread is not meant to be disturbed.
Since I know when the work appears it seems a good idea to tell the thread, instead of having it check over and over again.

How can a thread be put to a 'lighter sleep' to be able to wake up alone each second or at a command from other thread?

//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

线程不应进入Sleep() ,而应在AutoResetEventManualResetEvent上调用WaitOne() ,直到其他线程在同一resetevent对象上调用Set()为止。

You can use an AutoResetEvent for this - just call Set() to signal work needs to be done and have your thread wait for it to be called using WaitOne() .

This means the threads that are communicating this way share the same AutoResetEvent instance - you can pass it in as a dependency for the thread that does the actual work.

How about using a blocking queue, with 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();
        }
    }
}

Then thread 1 becomes

BlockingQueue<Action> _workQueue = new BlockingQueue<Action>();

while (true)
{
    var workItem = _workQueue.Dequeue();
    workItem();
}

And the other thread:

_workQueue.Enqueue(DoWork);

NB: you should probably use the built in type if you're using .Net 4 BlockingCollection using Add and Take instead of Enqueue and Dequeue.

Edit: Ok. If you want it really simple...

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

and

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

I'n not an expert with threads, but maybe EventWaitHandle is what you're looking for. Check this link

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM