我正在使用一个AutoResetEvent,其中可以对一个事件进行多个Set调用(异常处理)。有时会调用额外的Set,因此当代码对WaitOne事件进行第二次调用时,它只是直接通过,因为门已经打开。
解决方案是在WaitOne之前调用Reset。有没有更干净的解决方案,或者这是唯一的解决方案?示例代码:
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();
}在异常处理之后,我需要再次调用DoSomeWork,但是由于Set可能在多个异常(或重新抛出的异常)中被调用,所以WaitOne只是流过。
我的解决方案是总是在WaitOne之前调用Reset。这是合适的解决方案,糟糕的设计,还是有不同类型的事件来处理这种情况?
编辑:我只是将注释的重置(建议的解决方案)移到了事件旁边。
发布于 2010-11-06 05:02:12
我担心的是,如果在调用WaitOne()之前调用Reset(),如果没有调用任何Set(),那么就会遇到麻烦。如果您调用Set(),然后在调用WaitOne()之前立即单击Reset(),则可能会发生这种情况。即使你调用了Set()两次,也不能保证你不会在两次之后调用Reset(),阻塞线程而没有释放机制。
理想情况下,您应该有一个try..catch..finally块,并在finally块中调用Set(),而不是让异常处理跨方法传播。这对你有效吗?
Hans是正确的,在这种情况下,多线程是不必要的。我所关心的问题只有在您真正使用多线程调用WaitOne()时才适用。
我还担心你不止一次调用set ...这是否意味着当第一个集合被调用时,资源真的应该保持锁定状态?如果你仍然能够第二次点击Set(),对我来说,这说明你仍然在执行使用共享资源的代码。在这种情况下,您不希望对WaitOne()的调用解除阻塞。
另请注意,从MSDN:
不能保证每次调用Set方法都会释放一个线程。如果两个调用离得太近,导致第二个调用在线程释放之前发生,则只释放一个线程。就好像第二次调用没有发生一样。
在任何情况下,您的代码似乎应该要么抛出异常,要么运行到完成,但不能两者兼而有之。也就是说,你不应该两次调用Set()。
发布于 2010-11-06 04:50:37
这不是真正的问题,WaitOne()调用会自动重置事件。毕竟,您使用的是AutoResetEvent,而不是ManualResetEvent。这里的关键短语是自动重置。
看到它直接通过WaitOne()调用也是很正常的。你已经有了一个很好的多核CPU,当你调用Start()时,线程就立即启动了,并且只用了几微秒就完成了工作。毫秒,不管怎么说,比你眨眼的时间还快。
也许更重要的是,这里不需要线程。启动一个,然后等待它结束是没有意义的。只需直接调用DoSomeOtherStuff()即可。
https://stackoverflow.com/questions/4109395
复制相似问题