Click here to Skip to main content
15,891,529 members
Please Sign up or sign in to vote.
3.75/5 (4 votes)
Hi!

Has anybody met the following problem - there is a thread A that should notify another thread B and then wait for a backward notification from the thread B. Something like that:

AutoResetEvent BNotifier = ...;
AutoResetEvent ANotifier = ...;

Thread A:

1) BNotifier.Set();
...
2) ANotifier.WaitOne();

Thread B:

3) BNotifier.WaitOne();
...
4) ANotifier.Set();

-----

The problem with the code above is that between 1) and 2) thread A may be preempted and this way 4) will be called before the 2). If we suppose that there are several other threads already waiting for ANotifier, state of the ANotifier may be changed back to non-signaled before the call to 2), and this way Thread A will be waiting forever.

The following code solves this problem in most situations, but it is not reliable, is error-prone and ineffective:

Thread A:

Tast.Factory.StartNew( () =>
{
Thread.Sleep( 1000 );
BNotifier.Set();
});
ANotifier.WaitOne();

Are there any other ways to ensure Thread B to be notified only after the Thread A starts waiting for the ANotifier?
Posted
Comments
Sergey Alexandrovich Kryukov 23-Apr-12 15:02pm    
OK, very nice, you have described the deadlock. Now, you need to explain why would you write such weird code in first place? What was you goal.

Otherwise, you question can be classified into something I call "making yourself difficulties to bravely overcome them". :-)
No, that does not look like intended EventWaitHandle usage. The question would not make any sense before you explain your idea.

--SA
kkhippytch 24-Apr-12 3:08am    
My initial goal was, if simplify it, to implement a sort of "approval" process - that is, there is an Approval class and several threads (of type A in the example above), each of which should call Approval.Approve() method.

Approve() method first notifies management thread (Thread B) using BNotifier event and then blocks its calling thread (of type A) till the time Thread B do some work and notify about that fact (using NotifyA event).

Thread B, in turn, waits for all approvers to approve (and get into waiting state), then do some work and, when this work is completed, notify all blocked approvers, using ANotifier event. Then next approval cycle is started.

Line 1) in the example (BNotifier.Set()) is used to notify management thread B to check if it is the last one of all registered approvers has just approved and come into the waiting state, and thus current approval cycle is completed and management thread B is now allowed to do its work (for which it has been waiting for all approvers to approve).

Frankly speaking, I`ve found out that method WaitHandle.SignalAndWait(BNotifier, ANotifier); would solve my problem were it atomic. But the problem is that it is not atomic, according to MSDN - before the signaling to BNotifier and starting waiting for ANotifier there may be a "gap" in a truly parallel environments.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900