我正在使用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。这是适当的解决方案,糟糕的设计,还是会有不同类型的事件来处理这种情况?
编辑:我刚刚在活动旁边移动了评论重置(建议的解决方案)。
答案 0 :(得分:4)
这不是一个真正的问题,WaitOne()调用会自动重置事件。毕竟,您使用的是AutoResetEvent,而不是ManualResetEvent。这里的关键词是自动重置。
通过WaitOne()调用看到它是很正常的。你有一个很好的多核心CPU,当你调用Start()时,线程立即启动,并且只需几微秒即可完成工作。毫秒,无论如何,比眨眼之快。
也许更重要的是,你在这里不需要一个线程。从一个开始,然后等待它完成是毫无意义的。只需直接调用DoSomeOtherStuff()即可。
答案 1 :(得分:2)
我担心的是,如果你在WaitOne()之前调用Reset(),如果没有调用Set()就会遇到麻烦。如果你调用Set(),然后在点击WaitOne()之后立即点击Reset(),则可能会发生这种情况。即使你两次调用Set(),也不能保证你不会在两者之后都调用Reset(),阻塞没有释放机制的线程。
理想情况下,您将有一个try..catch..finally块,并调用finally块中的Set(),而不是跨方法分布您的异常处理。这对你有用吗?
汉斯是正确的,在这种情况下,多线程是不必要的。我的问题仅适用于您对WaitOne()的调用真正多线程。
我还担心你不止一次调用set ...这是否意味着当调用第一个set时,资源应该保持锁定状态?如果你仍然能够第二次点击Set(),那么我说你仍在执行使用共享资源的代码。在这种情况下,您不希望对WaitOne()的调用取消阻止。
另请注意,来自MSDN:
无法保证每次调用Set方法都会释放一个线程。如果两个调用太靠近,那么第二次调用在线程释放之前发生,则只释放一个线程。就好像第二次通话没有发生一样。
在任何情况下,您的代码似乎应该是抛出异常或运行完成的路径,而不是两者。 I.E.你不应该两次调用Set()。