У меня есть следующий шаблон проектирования:
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() внутри блока catch try для игнорирования исключения не является чистой, учитывая, что исключение может происходить довольно часто.
Что вы предложите как лучший и самый простой способ достичь цели вышеуказанного шаблона кода (т.е. ожидание создания события), не сталкиваясь с такой проблемой?
Изменить:. Благодаря вашим ответам я создал следующее расширение и заменил mre.Set() на mre.TrySet():
public static void TrySet(this ManualResetEvent mre) {
if (!mre.SafeWaitHandle.IsClosed) mre.Set();
}