tengo el siguiente patrón de diseño:¿Cómo comprobar si ManualResetEvent se ha eliminado al intentar establecerlo() en un EventHandler?
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;
}
}
Mi problema es que si OnEvent
se eleva después de que los WaitOne
tiempo de espera y pasos de ejecución de cada bloque using, el manejador onEvent
evento local seguirá llamándose y tratar de configure el ManualResetEvent mre
que ya habrá sido eliminado, aunque onEvent
no debería estar registrado en OnEvent
.
Una solución sencilla sería la de comprobar si mre
ya se ha dispuesto, pero por desgracia no hay ningún campo, y creo envolver mre.Set()
dentro de un bloque catch tratar de ignorar la excepción no está limpio dado que la excepción podría ocurrir muy frecuentemente.
¿Qué sugieres como la mejor y más simple forma de lograr el propósito del patrón de código anterior (es decir, esperar a que se genere un evento) sin toparse con este tipo de problema?
Editar: Gracias a sus respuestas, he creado la siguiente extensión y sustituido mre.Set()
con mre.TrySet()
:
public static void TrySet(this ManualResetEvent mre) {
if (!mre.SafeWaitHandle.IsClosed) mre.Set();
}
¿Podría dar más detalles sobre los requisitos de su aplicación? Usted pregunta por "la mejor y más simple forma de lograr el propósito del patrón de código anterior", pero eso nos deja adivinando en qué se basan sus requisitos con respecto a su código actual. – Justin
¿Causa problemas al ejecutar Set() en MRE descartado? – sll
Sí mre.Set() en mre dispuesto emitirá una excepción ... –