отсоединение анонимных слушателей от событий в C # и сборки мусора - PullRequest
4 голосов
/ 07 марта 2012

Допустим, у меня есть класс с именем Dialog, который расширяет форму. В диалоговом окне есть текстовое поле и кнопка ОК, и когда пользователь нажимает кнопку ОК, значение текстового поля возвращается через событие:

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();
        };

В моей форме вызова я создаю экземпляр диалога в локальном методе:

  private void Foo()
  {
        Dialog D = new Dialog("blah blah");
        D.DialogValueReturned += (dialog, evt) =>
            {

               //do something with evt.Value

            };


        D.ShowDialog();
   }

Этот диалог может быть создан пользователем десятки или даже сотни раз в течение дня.

Удаляет ли сборщик мусора все, что связано с экземпляром диалога, автоматически, когда область действия покидает закрытый метод, включая всю информацию для анонимного слушателя?

Спасибо

Ответы [ 2 ]

2 голосов
/ 07 марта 2012

Издатель события сохраняет сильную ссылку на каждого подписчика.Если издатель живет дольше, чем подписчики, подписчики будут закреплены в памяти, пока издатель присутствует.

В вашем примере издатель существует только в рамках вашего частного метода, поэтому оба диалоговых окнаи обработчик будет собирать мусор в какой-то момент после возврата метода.

Я бы порекомендовал выполнить рекомендации dot Framework для публикации события , которое предлагает использовать защищенный виртуальный метод длявызвать события.

0 голосов
/ 07 марта 2012

Анонимная функция приведет к тому, что функция-член будет автоматически сгенерирована компилятором. Сгенерированное компилятором имя будет содержать недопустимые символы в C #, чтобы вы не могли назвать другого члена в вашем классе с таким же именем. Кроме этого, он будет вести себя абсолютно идентично обычным методам, связанным с событием, и, таким образом, все задействованные ресурсы будут собираться мусором.

И, как примечание к проекту, поскольку вас интересует значение, возвращаемое из диалогового окна, я бы не советовал использовать событие для уведомления о закрытии диалогового окна. Вместо этого вы можете заключить код в статический метод, например, в котором вы открываете диалоговое окно, ждете цикла событий, пока диалоговое окно не будет закрыто, и читаете ввод от пользователя, возвращая входные данные в формате, который более подходит для дальнейшей обработки. Это потребует от вас открыть модальное окно. Вот пример:

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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...