BackgroundI use threads a lot and, with them, I use synchronization objects a lot. But, except for some minor exceptions, the Synchronization objects are unmanaged resources. For a long time I used them, but recently I understood better how to use the Monitor methods, Wait and Pulse/PulseAll, and with it I was able to create full managed synchronization primitives.
EventWaitHandlesOne of the simplest ways to pass messages from one thread to another, and to wait for those messages, is to use some kind of EventWaitHandle, usually AutoResetEvent.AutoResetEvent has many problems as it uses unmanaged resources, it's very slow to create and if you Dispose it when there are threads waiting for it, well, those threads will be kept waiting forever. When I first saw Pulse I thought it could solve the problem, but the MSDN documentation says to avoid it. And, in fact, Pulse alone does not give the same result, as Pulse will only release an already waiting thread. It will not keep the state "signalled" if there are no threads waiting making the next thread to try to wait to be released immediately. But, there is a way to solve it. By using a boolean variable.So, to signal the object, we do something like this:lock(_lock)
{
_value = true;
Monitor.Pulse(_lock);
}And the wait waits only if the signal is not already signalled. If it is already signalled, it can reset the signal and return immediately. lock(_lock)
{
while(!_signalled)
Monitor.Wait(_lock); _value = false;
}Ok. With this simple structure, I have the equivalent of AutoResetEvent.Set() and AutoReset.WaitOne(). Read more: Codeproject
QR:
EventWaitHandlesOne of the simplest ways to pass messages from one thread to another, and to wait for those messages, is to use some kind of EventWaitHandle, usually AutoResetEvent.AutoResetEvent has many problems as it uses unmanaged resources, it's very slow to create and if you Dispose it when there are threads waiting for it, well, those threads will be kept waiting forever. When I first saw Pulse I thought it could solve the problem, but the MSDN documentation says to avoid it. And, in fact, Pulse alone does not give the same result, as Pulse will only release an already waiting thread. It will not keep the state "signalled" if there are no threads waiting making the next thread to try to wait to be released immediately. But, there is a way to solve it. By using a boolean variable.So, to signal the object, we do something like this:lock(_lock)
{
_value = true;
Monitor.Pulse(_lock);
}And the wait waits only if the signal is not already signalled. If it is already signalled, it can reset the signal and return immediately. lock(_lock)
{
while(!_signalled)
Monitor.Wait(_lock); _value = false;
}Ok. With this simple structure, I have the equivalent of AutoResetEvent.Set() and AutoReset.WaitOne(). Read more: Codeproject
QR:
0 comments:
Post a Comment