I'm using an AutoResetEvent where multiple Set calls can be made on an event (Exception handling). There are times when an extra Set is called, thus when the code makes a second call on a WaitOne event, it just passes right through because the gate has already been opened.
The solution is to call Reset right before the WaitOne. Is there a cleaner solution or is this the only way to do it? Example code:
private void DoSomeWork()
{
Thread thrd = new Thread(new ThreadStart(DoSomeOtherStuff));
thrd.Start();
//mEvt.Reset();
mEvt.WaitOne();
//continue with other stuff
}
private void DoSomeOtherStuff()
{
/* lots of stuff */
mEvt.Set();
}
private void ExceptionTriggerNeedsToBreakOutOfDoSomeWork()
{
mEvt.Set();
}
After the exception is handled, I need to call DoSomeWork again, but since Set may have been called in multiple exceptions (or rethrown exceptions), the WaitOne just flows through.
My solution is to alwa开发者_开发问答ys call Reset before the WaitOne. Is this the approriate solution, poor design, or is there a different type of event that will handle this scenario?
EDIT: I just moved the commented Reset (proposed solution) next to the event.
This is not a real problem, the WaitOne() call automatically resets the event. After all, you used an AutoResetEvent, not a ManualResetEvent. Key phrase here is Auto Reset.
Seeing it steaming right through the WaitOne() call is pretty normal too. You've got a nice multiple core CPU, the thread got started right away when you called Start() and didn't take but a few microseconds to get the job done. Milliseconds, whatever, faster than the blink of your eye.
Perhaps more to the point, you just don't need a thread here. Starting one, then waiting for it to finish is pointless. Just call the DoSomeOtherStuff() directly.
My concern would be that if you call Reset() before WaitOne(), you're in trouble if no Set() is ever called. This might happen if you call Set(), then hit Reset() immediately afterwards, before hitting WaitOne(). Even if you're calling Set() twice, there's no guarantee you won't call Reset() after both, blocking the thread with no mechanism for release.
Ideally, you would have a try..catch..finally block, and call the Set() in the finally block, and not have your exception handling spread across methods. Does that work for you?
Hans is correct that in this scenario, the multithreading is unnecessary. My concerns only apply if you are truly multithreading with your calls to WaitOne().
It also concerns me that you're calling set more than once... does that mean that when the first set is called, the resource should really remain locked? If you're still able to hit Set() a second time, to me that says you're still executing code that works with shared resources. In which case you don't want the call to WaitOne() to unblock.
Also note, from the MSDN:
There is no guarantee that every call to the Set method will release a thread. If two calls are too close together, so that the second call occurs before a thread has been released, only one thread is released. It is as if the second call did not happen.
In any case, it seems like your code should either go the route of throwing an exception, or running to completion, but not both. I.E. you shouldn't be calling Set() twice.
精彩评论