Что происходит с формой, когда ThreadPool WaitCallback вызывает ее после закрытия? - PullRequest
3 голосов
/ 04 марта 2012

Давайте предположим, что внутри формы Windows я запускаю долгосрочную задачу, подобную этой:

ThreadPool.QueueUserWorkItem(new WaitCallback(UpdateDailyTasksChart));

Затем эта функция выполняется некоторое время, но я закрываю окно до его завершения.

private void UpdateDailyTasksChart (object param)
{
  //Call Data Access Layer, go get MySQL Data. But I close the Form.
  UICallback(chartData); //The Form is closed when this is executed.
}

А теперь вот что делает UICallback:

private delegate void UICallbackDel(object chartData);
private void UICallback (object chartData)
{
  if (InvokeRequired)
  {
    this.Invoke(new UICallbackDel(UICallback), chartData);
  }
  else
  {
    aButtonOnMyForm.Visible = false; //But the Form has been closed!
  }
}

Любопытно, что этот код не вылетает.

Я установил точки останова в событии Form_Closed, и оно выполняет . Я не проверял, существует ли форма, например, объявив ее переменной класса. Но я думаю, что это так.

Итак, вопрос в том, что сборщик мусора будет собирать Форму только после завершения моей цепочки? Или что это происходит?

Ответы [ 3 ]

4 голосов
/ 04 марта 2012

Здесь есть два момента:

  1. Если вы явно распоряжаетесь формой, вы можете ожидать поднять ObjectDisposedException при выполнении делегата рабочего элемента.
  2. Ваш делегат рабочего элемента содержит ссылку на форму через this, InvokeRequired (что, в свою очередь, ссылается на this) и aButtonOnMyForm. Следовательно, ваша форма не подходит для сборки мусора, если поток ThreadPool не завершил выполнение. Вот почему код не падает. (Примечание: this всегда доступен неявным образом.)

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

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

Сборщику мусора все равно, является ли объект «закрытым», «утилизированным» или чем-то в этом роде.Это заботится только о том, доступен ли объект.И в вашем случае форма по-прежнему доступна с помощью this (неявно или явно).Вот почему ваше приложение не падает.

Конечно, если объект закрыт или расположен или что-то в этом роде, он имеет право выбросить ObjectDisposedException или аналогичный для любого метода, который вы вызываете.Но это, конечно, не обязательно.

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

Возможно, вы захотите взглянуть на эту запись.

Как правило, вы можете или не можете получить ObjectDisposedException в зависимости от того, что GC делает в то время, когда вы пытаетесь вызвать в форме. Вы можете попытаться поймать его, но он не может быть надежно проверен, так что это скорее взлом, чем что-либо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...