Edit: I'd like to plead temporary insanity for even asking this question, but it made sense at the time (see edit 2 below).
For a .NET 3.5 project, I have two types of resources (R1 and R2) that I need to check the availability of. Each resource type can have (say) 10 instances at any time.
When one of either types of resources becomes available, my worker thread needs to wake up (there is a variable number of threads). In an earlier implementation, there was only one resource type, for which I used a Semaphore to check availability.
Now I need to wait on two separate Semaphores (S1 and S2) that track availability of the resources.
WaitHandle[] waitHandles = new WaitHandle[] { s1, s2 };
int signalledHandle = WaitHandle.WaitAny(waitHandles);
switch (signalledHandle)
{
case 0:
// Do stuff
s1.Release();
case 1:
// Do stuff
s2.Release();
}
There is one problem with this however. From the MSDN documentation on WaitAny
:
If more than one object becomes signaled during the call, the return value is the array index of the signaled object with the smallest index value of all the signaled objects.
This suggests that it's possible that I decreased both my Semaphore counts by 1 after calling WaitAny
. Because signalledHandle
will indicate that s1 was signalled, I will start using resource R1, and release it when I'm done. However, since I do not know if S2 was signalled or not, the availability count on this resource might now be off. If this happens 10 times, my Semaphore will be permanently 'empty' and resource R2 will not be used at all anymore.
What is the best way to deal with this? Should I switch from using two semaphores to simple counters and an AutoResetEvent to signal when either counter is changed? Am I missing some more elegant approach?
Edit 1:
According to Ravadre, only one of the Semaphores will actually be altered after WaitAny
. Slightly modifying his example seems to confirm this, but is there anyone that can point me to some piece of official documentation that specifies this?
Edit 2:
I was thinking about this on my way home. Only then I realized that this must be true for WaitAny
to be of any use. This problem would not be restricted to Semaphores, but just about any type of synchronization object, making WaitAny
practically useless.