开发者

Clearing or checking for event handlers in C#

开发者 https://www.devze.com 2023-03-25 19:48 出处:网络
I have some C# code that updates some properties of an object. I have an event handler def开发者_如何学Goined to help me respond when the update process is done. Unfortunately, I\'ve learned that this

I have some C# code that updates some properties of an object. I have an event handler def开发者_如何学Goined to help me respond when the update process is done. Unfortunately, I've learned that this event is getting fired multiple times. I suspect this is happening because the event handler is being set at the wrong time. Currently, it is being set like the following:

myObject.Update_Succeeded += new EventHandler(myObject_Update_Succeeded);

Due to the complexity of the code, I'm having a difficult time of tracking down where it should be set. I would like to only set the event handler it hasn't been previously set. Because of this, I want to do something like this:

ClearEventHandlers(myObject);

or

myObject.Update_Succeeded = null;
myObject.Update_Succeeded += new EventHandler(myObject_Update_Succeeded);

Is there a way to accomplish what I'm trying?

Thank you!


Yes, you can customize the add/remove accessors of your event. This article describes these accessors. But you can do something like:

class MyClass
{
    private EventHandler _myEvent;

    public event EventHandler MyEvent
    {
        [MethodImpl(MethodImplOptions.Synchronized)]
        add 
        { 
            _myEvent = (EventHandler)Delegate.Combine(_myEvent, value);
        }
        [MethodImpl(MethodImplOptions.Synchronized)]
        remove 
        { 
            _myEvent = (EventHandler)Delegate.Remove(_myEvent, value); 
        }
    }

    public void ClearMyEvent() {
        _myEvent = null;
    }
    ...
}


You should be able to remove a handler using the subtract operator like below

myObject.Update_Succeeded -= new EventHandler(myObject_Update_Succeeded);

Or check this out for a way to remove all event handler if you are in doubt

How to remove all event handlers from a control


Proper way should be to detach the handler from each event after you no longer use it:

public class MyObjectListener
{
     private readonly MyObject _object;
     public class MyObjectListener(MyObject obj)
     {
          _object = obj;
          Attach();
     }

     // adds event handlers
     private void Attach()
     {
         obj.UpdateSucceeded += UpdateSuceededHandler;
         obj.UpdateFailed += UpdateFailedHandler;
     }

     // removes event handlers
     private void Detach()
     {
         obj.UpdateSucceeded -= UpdateSuceededHandler;
         obj.UpdateFailed -= UpdateFailedHandler;
     }

     ...
}

The only thing you need to decide is where to call the Detach method. For example, you can call it in the handler itself:

     private void UpdateSuceededHandler(object sender, Data args)
     {
         Detach();
         // do something when it succeeds
     }

     private void UpdateFailedHandler(object sender, Data args)
     {
         Detach();
         // do something when it fails
     }

Or, you could allow users of MyObjectListener to tell it that it no longer needs to listen to the attached object:

     public void StopListening()
     {
         Detach();
     }

An object which raises an event should not allow its listeners to modify the event invocation list. Each event listener should subscribe or unsubscribe its own event handlers only.


You better set event handler on the initialization of your object i.e. in your Constructor.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号