我有以下设计模式:
var myObjectWithEvents = new ObjectWithEvents();
using (var mre = new ManualResetEvent(false)) {
var onEvent = new EventHandler<EventArgs>((sender, e) => { mre.Set(); });
try {
myObjectWithEvents.OnEvent += onEvent;
var task = Task.Factory.StartNew(() => {
myObjectWithEvents.DoSomethingThatShouldRaiseAnEvent();
});
var timedOut = !mre.WaitOne(10000);
}
finally {
myObjectWithEvents.OnEvent -= onEvent;
}
}
我的问题是,如果
OnEvent
超时后引发了WaitOne
,并且执行了using块之外的步骤,则仍然会调用本地onEvent
事件处理程序,并尝试设置已经处置的ManualResetEvent mre
,即使onEvent
应该已经未从OnEvent
注册。一个简单的解决方法是检查
mre
是否已被处置,但不幸的是没有此类字段,并且我相信将mre.Set()
包裹在try catch块中以忽略该异常并不干净,因为该异常可能会经常发生。您如何建议实现上述代码模式(即等待引发事件)的最佳和最简单方法,而又不会遇到此类问题?
编辑:由于您的回答,我创建了以下扩展并将
mre.Set()
替换为mre.TrySet()
: public static void TrySet(this ManualResetEvent mre) {
if (!mre.SafeWaitHandle.IsClosed) mre.Set();
}
最佳答案
您可以尝试通过mre.SafeWaitHandle.IsClosed属性进行检查