Unsubscribing from an event

落花浮王杯 提交于 2021-01-27 07:11:59

问题


I have the following function.

What it does is, given a Control (most likely a windows form) i want to have all of the controls contained that "obey" the Rules ( a function screening the controls i want ) subscribe to an event (lets say KeyDown).

The question is: how do i unsubscribe? Or more importantly, do i need to?

Since i will be using this one on the Load event of forms on the form itself will i really need to unsubscribe if the form closes?

(after some light reading and a little understanding of the GC i suspect i don't need to unsubscribe but I'm not sure)

//an example of using the function
    private void Form1_Load(object sender, EventArgs e)
    {
        MyEventHandler.CreateKeyDownEventHandlers(this);
    }

//the function
    public static void CreateEventHandlers(Control Ctrl)
    {
        foreach (Control c in Ctrl.Controls)
        {
            //bool Rules(Control) a function that determines to what controls'
            //events to apply the handler 
            if ( Rules(c) )
            {
                c.KeyDown += (s, e) =>
                {
                  // do something
                };

            }

            //a control might be a groupbox so we want their contained
            //controls also
            if (c.Controls != null)
            {
                if (c.Controls.Count > 0)
                {
                    CreateEventHandlers(c);
                }
            }

        }
    }

This is my first try with events, delegates, anonymous functions and lambdas so if i did something really stupid tell me.


回答1:


First, I think you cannot unsubscribe an anonymous function unless it's assigned to a handler variable and that variable is addded to and then removed from the event.

Whether you need to unsubscribe: Think about the object lifetimes. You create anonymous functions in a static method and attach the to controls of which I assume you control the lifetimes.

When you dispose one of these controls, they will no longer be referencing the anonymous functions and the GC can kill them (the anonymous functions), so you don't need to unsubscribe.

If the situation was reversed and something that was created in the static method referenced the controls, as if a control delegate was added to an event in the static context, then the GC couldn't take care of the controls until the reference to them was removed, which wouldn't happen if it was done in the static method.




回答2:


If you are creating the Form once, and these handlers also once at the beginning, then you don't really need to clean anything.

If you create it multiple times though (e.g. you create the form many times when the user clicks on a button), then you need to be careful. And here the answer depends on what exactly is in the handlers:

c.KeyDown += (s, e) =>
            {
              // do something
            };

In general assigning a delegate to an event can cause a dependency cycle from GC's point of view, e.g. imagine that a Form contains control A, and registers to an event on A. Then the form cannot be disposed until A is disposed, and A cannot be disposed until the form is disposed (because it references the form indirectly through the callback). If you only create the form together with control A then its ok (GC will get rid of both at the same time), but when you create controls A dynamically then you can end-up with memory leak.




回答3:


You can unsubscribe from an event by using

yourobject.Yourevent-= YourSubscribedFunction;

This will unsubscribe this function from the event.

About the second part of your question:

You do not need to unsubscribe if the object containing the event is destroyed.

I am not sure what happens if the subscribing object is disposed but my tests indicate that the function is still called, eventhough the object no longer exists.

ClassA a = new ClassA();
using (ClassB b = new ClassB()) // implements IDisposable
{
    b.SubscribeToFoo(a); // b subscribes to FooEvent of ClassA
    a.DoFoo(); // a executes FooEvent
}
GC.Collect(); // Run Garbage Collector just to be sure
a.DoFoo(); // a executes FooEvent

The subscribed method of ClassB is called, eventhough b is disposed.



来源:https://stackoverflow.com/questions/2108422/unsubscribing-from-an-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!