Detaching anonymous listeners from events in C # and garbage collection

Say I have a Dialog class that extends a form. There is a text field in the dialog box and the OK button, and when the user clicks OK, the value of the text field is returned through the event:

public class Dialog: Form { public delegate void onDialogValueReturned(object sender, DialogEventArgs e); public event onDialogValueReturned DialogValueReturned; . . . OKButton.Click += (sender, evt) => { DialogEventArgs e = new DialogEventArgs(); e.Value =myTextBox.Text; DialogValueReturned(this, e); this.Close(); }; 

In my call form, I create a dialog in the local method:

  private void Foo() { Dialog D = new Dialog("blah blah"); D.DialogValueReturned += (dialog, evt) => { //do something with evt.Value }; D.ShowDialog(); } 

During the day, this dialogue can be triggered dozens or even hundreds of times.

Does the garbage collector collect everything related to the dialogue instance when the area exits the private method, including all the plumbing for the anonymous listener?

thanks

+4
source share
2 answers

The event publisher maintains a strong link to each subscriber. If the publisher lives longer than the subscribers, then the subscribers will be fixed in memory while the publisher is present.

In your example, the publisher exists only within the framework of your private method, so both the dialog and the handler will be collected at a certain point after receiving the method.

I would recommend following the dot net framework to post an event that suggests using a secure virtual method to call events.

+2
source

An anonymous function will cause the member function to have its name automatically generated by the compiler. The name generated by the compiler will contain characters that are illegal in C # to ensure that you cannot name another member in your class with the same name. In addition, it will behave absolutely identical to the normal methods associated with the event, and thus all resources involved will be collected in garbage.

And as a design note, since you are interested in the value returned from the dialog box, I would advise you not to use the event to notify you when the dialog box closes. Instead, you can, for example, wrap your code with a static method in which you open a dialog box, wait for the event loop until the dialog box is closed and reads input from the user, returning the input data in a more suitable format for further processing . This will require you to open a modal window. Here is an example:

 public class MyDialog : Form { // We can make the constructor private, as this class is instantiated only // in the Show method. private MyDialog() { } // ... public class ReturnValue { public string Foo { get; set; } // ... } public static ReturnValue ShowModal(/* any params, if required */) { ReturnValue result = new ReturnValue(); MyDialog dialog = new MyDialog(); if(DialogResult.OK == dialog.ShowDialog(null)) { // We can access private members like txtFoo since we are within the class. result.Foo = dialog.txtFoo.Text; // ... } return result; } } 
0
source

Source: https://habr.com/ru/post/1400089/


All Articles