Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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();
    }
like image 900
Erwin Mayer Avatar asked Jan 25 '12 14:01

Erwin Mayer


2 Answers

ManualResetEvent.SafeWaitHandle.IsClosed

Seems strange, but the only thing that the dispose does is to close the safeHandler, which is the only object that its the dispose intended to...

The Dispose of the SafeWaitHandle, changes this property from False to True.

like image 76
Guido Zanon Avatar answered Oct 01 '22 15:10

Guido Zanon


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

like image 41
Viacheslav Smityukh Avatar answered Oct 01 '22 15:10

Viacheslav Smityukh