I am planning to use Auto reset Event Handle for Inter Thread communication.
EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.AutoReset);
My producer thread code look like below
produceSomething();
handle.Set();
In the consumer thread, I have to download data for every one minute or when producer
is called Set method
try
{
while(true)
{
handle.WaitOne(60000, false);
doSomething(); // Downloads data from Internet.
// Takes lot of time to complete it.
}
}
catch(ThreadAbortException)
{
cleanup();
}
My question is if consumer thread is running doSomething function and producer calls set function, what would be state of Auto reset event object?
My requirement is as soon as producer calls set method I have to download fresh data from the Internet. If doSomething function is running, when Producer calls set method, I have to interrupt it and call again.
An auto-reset event is like a gate that closes after the first thread goes through. If you set it while one or more threads are waiting then One thread wakes up, then the event is reset, the rest of the threads continue to wait.
If you set when no threads are waiting, then the first thread that calls handle.WaitOne will not wait, but it will cause the event to get reset and then continue on.
from http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
Calling Set signals AutoResetEvent to release a waiting thread. AutoResetEvent remains signaled until a single waiting thread is released, and then automatically returns to the non-signaled state. If no threads are waiting, the state remains signaled indefinitely.
If a thread calls WaitOne while the AutoResetEvent is in the signaled state, the thread does not block. The AutoResetEvent releases the thread immediately and returns to the non-signaled state.
The problem with auto-reset event in your scenario is that "setting" it do not supports queuing.
That is, setting an auto-reset event allows one thread to enter, if you set it again before any thread "consumes" your event, then that "set" will be lost. You might expect for two threads to be able to enter and consume whatever you have produced but in fact only ONE thread will be able to do that.
In your case, if you're producing at a faster rate than you're consuming then the auto-reset event might be missleading. Imagine this case.
The producer produces one item.
The consumer consumes the item (resets the event and starts downloading from inet)
The producer produces a second item.
The producer produces a third item.
The produce stops.
The consumer consumes the second item (resests the event and starts downloading again)
The consumer WON'T cosume the third item ever because the autoreset event has been reset.
Related
I have a thread that grabs messages from a concurrent queue and writes them to a network stream. The loop inside the thread looks like this:
while (!cancel.IsCancellationRequested)
{
messageBus.outboundPending.WaitOne();
var message = messageBus.GetFrom(Direction.Outbound);
if (message == null) { continue; }
MessageWriter.WriteMessage(networkStream, message, cancel, OnStreamClose).Wait(cancel);
}
The requirement is that the thread stops if the cancellation token is set. However, since it waits for pending messages in the queue, the thread will stay blocked. How could I "combine" both the cancellation token and the outbound event so that if either of them are set, the thread unblocks?
The only convoluted way that I can think of to make it work is to replace the outboundPending event with a new third event, and start two new threads: one that waits for the outbound event, and another that waits for the cancel event, and have both of them set the third event when they unblock. But that feels really bad.
Try WaitHandle.WaitAny and include the CancellationToken.WaitHandle.
A discussion of a cancellable WaitAll can be found here
Use the WaitOne(TimeSpan) method. It will return true if it was signaled, and false if the timeout was reached.
e.g, if you send TimeSpan.FromSeconds(1) and a second has passed without a signal, the execution will continue and the method will return false. If the signal was given, it will return true.
Consider the following test snippet:
// act
AutoResetEvent workDoneEvent = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(delegate
{
ProcessAndSignal(processor, workDoneEvent);
}, null);
// let worker thread have a go
workDoneEvent.WaitOne();
blockingFetcher.WaitForNextMessage = false;
// assert
Assert.That(processor.StopCause, Is.Null);
}
private static void ProcessAndSignal(MessageProcessor processor, AutoResetEvent workDoneEvent)
{
workDoneEvent.Set();
// this invocation will block until the WaitForNextMessageFlag is set
processor.ProcessMessages();
}
Ideal scenario:
ProcessAndSignalMethod is queued on the thread pool but does not start to execute.
The main thread blocks (autoResetEvent.WaitOne())
A worker thread starts to execute the "ProcessAndSignal" method
The worker threads has enough time to signal the flag and start execution of the ProcessMessages method
The main thread is spawned back into life and sets the property which will cause the ProcessAndSignal method to complete gracefully
Can the following scenario occur?
1) ProcessAndSignal() will start to execute before the main thread sets the AutoResetEvent to WaitOne() which will cause a deadlock (the processor.ProcessMessages() will go into an infinitive loop)
Yes, the scenario can occur. Yes it can deadlock if you don't declare the bool variable as volatile. Just don't use a bool, use an event like you did.
The logic looks weird, it smells like you are trying to let the main thread wait for the processing to be completed. The workDoneEvent doesn't actually signal that the work was done. Right now the main thread will check the assert before the worker is done, that can't be good. If the intention was that it signals that the worker is done then ProcessAndSignal should be the one calling Set(), at the end of the method. And the main thread should call WaitOne().
If this is at all accurate then you just should not use QUWI, just call ProcessAndSignal directly without using a thread. Far more efficient, zero odds for threading problems.
As part of a windows service
I'm accepting incoming socket connection using
myListener.BeginAcceptSocket(acceptAsync, null)
The acceptAsync function executes on a seperate thread (just as expected).
When the service is requested to shutdown, I "signal" the threads that accepted and are currently working on the sockets, to finish up.
After signaling each thread to end,I need to block until they are all done. I have a list of threads, that I thought I could iterate through and Join each thread until they were all done.
Howerver it seems that these threads don't end, but return to the pool, so the Join will wait for ever.
How do I block until a thread is returned to the pool?
You shouldn't use Join in this case. Rather, you should use a series of WaitHandles (specifically, an AutoResetEvent or ManualResetEvent) which your threads will signal when they are done with their work.
You would then call the static WaitAll method on the WaitHandle class, passing all of the events to wait on.
The canonical pattern for doing this is to use a CountdownEvent. The main thread will increment the event to indicate that it is participating and the worker threads will do the same once they start. After the worker threads have finished they will decrement the event. When the main thread is ready to wait for completion it should decrement the event and then wait on it. If you are not using .NET 4.0 then you can get an implemention of a countdown event from part 4 of Joe Albahari's threading ebook.
public class Example
{
private CountdownEvent m_Finisher = new CountdownEvent(0);
public void MainThread()
{
m_Finisher.AddCount();
// Your stuff goes here.
// myListener.BeginAcceptSocket(OnAcceptSocket, null);
m_Finisher.Signal();
m_Finisher.Wait();
}
private void OnAcceptSocket(object state)
{
m_Finisher.AddCount()
try
{
// Your stuff goes here.
}
finally
{
m_Finisher.Signal();
}
}
}
The best way would be to change acceptAsync so that it signals on a semaphore, your main thread can then wait on that semaphore.
You don't have a lot of acces to or control over Threapool threads.
I'm using a single producer-single consumer model with a blocking queue. I would like for the producer, when it has finished producing, to wait for the queue to empty before returning.
I implemented the BlockingQueue suggested here by Marc Gravell.
In my model, the producer (renderer) is using events to notify the worker (printer) when a file has is being rendered (worker queues the item) and when every file has been rendered (finished).
Right now, when the renderer is done, the method ends and the worker gets killed, so I end up with 10-15 rendered files that haven't been printed.
I want the finished event handler to block until the queue has been emptied, e.g., when all the files are printed. I want to add something like a "WaitToClose()" method that will block until the queue is empty.
(Would having the worker thread set to IsBackground = true make a difference?)
How about adding an event to the queue:
private AutoResetEvent _EmptyEvent = new AutoResetEvent(false);
Then modify the Queue to set the event when it is empty, and you can block on the event.
Thinking it through further, however, when the queue is empty, the printer will still be printing the last item.
So, then you could join (block) on the worker thread.
Simpler idea: just block on the worker thread, and have the work thread finish (exit) when the queue is empty?
Suppose that ThreadA and ThreadB both call WaitOne() in that order on the same AutoResetEvent. When the event is set, why does ThreadB get released instead of ThreadA?
I ran a test to find out what happens when you set an AutoResetEvent on which mutiple threads are waiting:
private static void Test()
{
// two threads - waiting for the same autoreset event
// start it unset i.e. closed i.e. anything calling WaitOne() will block
AutoResetEvent autoEvent = new AutoResetEvent(false);
Thread thread1 = new Thread(new ThreadStart(WriteSomeMessageToTheConsole));
thread1.Start(); // this will now block until we set the event
Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
thread2.Start(); // this will now also block until we set the event
// simulate some other stuff
Console.WriteLine("Doing stuff...");
Thread.Sleep(5000);
Console.WriteLine("Stuff done.");
// set the event - I thought this would mean both waiting threads are allowed to continue
// BUT thread2 runs and thread1 stays blocked indefinitely
// So I guess I was wrong and that Set only releases one thread in WaitOne()?
// And why thread2 first?
autoEvent1.Set();
}
The code is of course not useful, it's just a simple example.
IIRC, which thread is released by an auto-reset event is unspecified. As everyone else mentioned, you want a manual reset event if you want to broadcast a condition. If you want to release an exact number (say exactly 3 of n), then you probably want to use a semaphore.
If you really want to dig into why the order might be different than you would expect, take a look at "Windows Internals" or anything that Mark Russinovich has written. Chances are that he explains the wait order on executive resources somewhere.
From MSDN
MSDN on ManualResetEvent: "Threads
that call WaitOne on the
ManualResetEvent will block, awaiting
the signal. When the controlling
thread completes the activity, it
calls Set to signal that the waiting
threads can proceed.
All waiting threads are released.
But for AutoResetEvent, MSDN says:
"Calling Set signals AutoResetEvent to
release a waiting thread.
AutoResetEvent remains signaled until
a single waiting thread is released, and then automatically
returns to the nonsignaled state. If
no threads are waiting, the state
remains signaled indefinitely.
"
On an AutoResetEvent, Set only releases one thread. You should use a ManualResetEvent to release multiple waiting threads.