0

Edit: this question is not about how to unsubscribe from events because I know how to do that if I want to. The question is about if there is a conflict with garbage collection in my specific scenario.

In some code I wrote a while ago I registered an event (CheckExecution, owned by isoDataTemp, see code below) by means of an anonymous method. But now it has come to my mind that assigning an anonymous method to an event is pretty evil because there is no way to unregister the method from the event, right? I once had a problem with an object that could not be garbage collected because an event was still pointing to it.

So I wonder if I can get into trouble with it here. My spontaneous reaction is "no, because the anonymous method belongs to the MainForm and this has longer lifetime than its isoDataTemp member". But I am not sure. What about closures? Does the anonymous method belong to MainForm at all. I am confused...

public partial class MainForm : Form
{
    // ...

    void BackgroundWorkerISOAnalysisDoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        int prog = 0;

        isoDataTemp.CheckExecution += () => 
        {
            prog += 12;
            if (prog > 100) prog = 100;
            worker.ReportProgress(prog);
            return !worker.CancellationPending;
        };

        isoDataTemp.Analyze();

        if (worker.CancellationPending) e.Cancel = true;
    }
}
oliver
  • 2,771
  • 15
  • 32
  • 1
    Possible duplicate of [How to remove a lambda event handler](https://stackoverflow.com/questions/1362204/how-to-remove-a-lambda-event-handler) – adjan Apr 26 '18 at 09:05
  • @Adrian: I can't see anything related to a blocked garbage collection in this question... – oliver Apr 26 '18 at 09:09
  • Your statement that ""the anonymous method belongs to the MainForm" should more correctly be "the anonymous method belongs to the isoDataTemp object". If the isoDataTemp object belongs to the Form then, by extension, the anonymous method does too. – Jazimov Apr 26 '18 at 09:29

1 Answers1

1

To unregister all event handlers for an event that you own, simply use this code:

isoDataTemp.CheckExecution = null;

Note that this works for anonymous and non-anonymous event handlers.

From your example, you can add this code to your OnFormClosing event, to ensure that events assign to your isoDataTemp object are properly and completely removed.

Note that if the isoDataTemp object is a child object of the form object, then it will be removed when your Form object is destroyed and will be garbage-collected along with the destroyed Form object instance, as expected.

Jazimov
  • 12,626
  • 9
  • 52
  • 59
  • This does not work for events (as opposed to ordinary delegates) because events only allow for the += and -= operators (at least from outside the containing class), but not the assignment operator. – oliver Apr 26 '18 at 09:18
  • That's what I meant by "event that you own". – Jazimov Apr 26 '18 at 09:20
  • It is obvious that isoDataTemp is the owner of the event, so I can't set it to null from the form. – oliver Apr 26 '18 at 09:21
  • In turn, you said isoDataTemp is a "member" (we can't see its declaration in your example), thus if you own the Form you also own that. – Jazimov Apr 26 '18 at 09:28
  • I appreciate your addressing my question. But I explicitly stated that I am subscribing to an event. Showing the declaration of this event doesn't add anything new than what is already obvious: CheckExecution is an event declared inside the class corresponding to the instance isoDataTemp. And no, the form doesn't own it. I tried it because I didn't trust my own knowledge. It doesn't work, period. – oliver Apr 26 '18 at 09:35
  • OK, I tried... I suppose my confusion is that this question involves anonymous methods, event handlers, object lifetime, garbage collection, with a code snippet presenting a theoretical problem. Our comments then introduced nuanced semantics ("belongs to" and "owns")--creating some miscommunication. I think the best way to investigate this is to implement IDisposable on the objects in question to see if and in what order they're being disposed of. However, I do hope someone else is better able to digest your question and provide an authoritative answer. – Jazimov Apr 26 '18 at 09:44
  • Thanks anyway! I have to apologize for any miscommunication. – oliver Apr 26 '18 at 09:56