Reputation: 2352
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
Upvotes: 1
Views: 2022
Reputation: 826
I'n not an expert with threads, but maybe EventWaitHandle is what you're looking for. Check this link
Upvotes: 0
Reputation: 19063
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);
}
Upvotes: 1
Reputation: 160892
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.
Upvotes: 4
Reputation: 42125
The thread shouldn't Sleep()
, it should call WaitOne()
on an AutoResetEvent
or ManualResetEvent
until some other thread calls Set()
on that same resetevent object.
Upvotes: 4