You're right.
But don't forget that the call to Pulse must be inside a lock
(Monitor.Enter) of the object the Wait call releases. This way it will never
wait forever.
The following example is a correct use of Wait/Pulse, with comments that
explain it:
private sometype threadSharedResource; // A thread-shared resource.
public void Method1()
{
// We lock the shared resource.
lock (threadSharedResource)
{
...
// We need to wait for the state of the resource to be changed.
// And the state will be changed by other thread/s,
// so we unlock, temporarily, the resource.
Monitor.Wait(threadSharedResource);
}
}
public void Method2()
{
// We lock the shared resource.
lock (threadSharedResource)
{
// We do work with the resource…
…
// And now we do an operation that changes the state of the resource.
// We know that maybe there are other threads waiting for the state
of the
// resource to change, so we pulse the lock we have, just in case
there
// were threads waiting, as I said.
Monitor.PulseAll(threadSharedResource);
// Depending on what you are doing, in some situations
// you could want to remove from the waiting-threads list
// only the one from the top of the list, in that case use Pulse.
// After the Pulse, the threads are moved from the waiting-list
// to the “ready-to-get-the-lock†list (I don’t remember the exact
// name at this time).
threadSharedResource.OperationThatChangesState(); // The operation.
} // Finally we leave the lock.
}
If this behavior doesn't like you, maybe Wait/Pulse is not what you're
looking for.
If the resource has more than one state you can do “sync objectsâ€
private object someStateSyncObj = new object();
…and lock them.
Now, a real example with a collection (it is said that a collection has only
one state, which is the contents of the collection itself):
private ArrayList arrayList = new ArrayList();
public void Method1() // Thread-safe method.
{
lock (arrayList)
{
// Imagine we need at least two items.
while (arrayList.Count < 2)
Monitor.Wait(arrayList);
// Do work with the items…
}
}
public void AddItem(object item) // Thread-safe method.
{
lock (arrayList)
{
Monitor.PulseAll(arrayList); // We’re gonna change the state.
// We could also do Pulse.
arrayList.Add(item);
}
}
public void RemoveItem(int index) // Thread-safe method.
{
lock (arrayList)
{
Monitor.Pulse(arrayList);
arrayList.RemoveAt(index);
}
}
I hope this was helpful.
And sorry for my bad english, I’m Spanish.