Ho il seguente modello di progettazione:Come verificare se ManualResetEvent è stato eliminato, quando si tenta di impostare() all'interno di 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;
}
}
Il mio problema è che se OnEvent
viene generato dopo le WaitOne
volte su e fasi di esecuzione fuori del blocco utilizzando, il gestore onEvent
evento locale sarà comunque chiamato e cercare di impostare ManualResetEvent mre
che sarà già stato eliminato, anche se onEvent
avrebbe dovuto essere registrato da OnEvent
.
Una soluzione semplice sarebbe quello di verificare se mre
è già stato smaltito, ma purtroppo non c'è tale campo, e credo che il confezionamento mre.Set()
all'interno di un blocco try catch per ignorare l'eccezione non è pulito dato che l'eccezione potrebbe verificarsi abbastanza frequentemente.
Che cosa suggeriresti come il modo migliore e più semplice per raggiungere lo scopo del modello di codice sopra (vale a dire in attesa di un evento da sollevare) senza incorrere in questo tipo di problema?
Edit: grazie alle vostre risposte, ho creato la seguente estensione e sostituito mre.Set()
con mre.TrySet()
:
public static void TrySet(this ManualResetEvent mre) {
if (!mre.SafeWaitHandle.IsClosed) mre.Set();
}
Potrebbe fornire maggiori dettagli sui requisiti dell'applicazione? Chiedete "il modo migliore e più semplice per raggiungere lo scopo del suddetto modello di codice", ma questo ci lascia indovinare quali sono le vostre esigenze basate sul vostro codice corrente. – Justin
Causa problemi durante l'esecuzione di Set() su MRE eliminato? – sll
Sì mre.Set() su Mre disposed genererà un'eccezione ... –