Search code examples
c#.netmultithreadingdesign-patternsdispose

How to check if ManualResetEvent has been disposed, when trying to Set() it inside an EventHandler?


I have the following design pattern:

    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;
        }
    }

My issue is that if OnEvent is raised after the WaitOne times out and execution steps out of the using block, the local onEvent event handler will still be called and try to set the ManualResetEvent mre which will have already been disposed, even though onEvent should have been unregistered from OnEvent.

A simple workaround would be to check if mre has already been disposed, but unfortunately there is no such field, and I believe wrapping mre.Set() inside a try catch block to ignore the exception is not clean given that the exception could occur quite frequently.

What would you suggest as the best and simplest way to achieve the purpose of the above code pattern (i.e. waiting for an event to be raised) without running into this kind of issue?

Edit: Thanks to your answers, I created the following extension and replaced mre.Set() with mre.TrySet():

    public static void TrySet(this ManualResetEvent mre) {
        if (!mre.SafeWaitHandle.IsClosed) mre.Set();
    }

Solution

  • You can try to check it by the mre.SafeWaitHandle.IsClosed property