У меня есть следующий шаблон дизайна:
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
и выхода из блока использования, локальный обработчик события 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();
}