c# - 当 ThreadPool WaitCallback 在关闭后调用 Form 时,Form 会发生什么情况?

标签 c# winforms multithreading

假设在 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 事件中放置了断点,它确实执行了。我没有检查表单是否仍然存在,例如,用类变量声明它。但我猜是这样。

所以问题是:GC 只会在我的线程结束时收集 Form?或者它会发生什么?

最佳答案

这里有两点:

  1. 如果您显式处理表单,您可能希望在工作项委托(delegate)执行时引发 ObjectDisposedException
  2. 您的工作项委托(delegate)通过 thisInvokeRequired(反过来引用 this)和 aButtonOnMyForm 持有对表单的引用。因此,只要 ThreadPool 线程尚未完成执行,您的表单就没有资格进行垃圾回收。这就是代码不会崩溃的原因。 (注意:无论如何,this 始终是隐式可访问的。)

由此得出的另一件事是,通常明智的做法是在表单关闭之前从表单中注销外部事件处理程序,以免造成内存泄漏。如果你注册了一个 lambda 表达式或匿名委托(delegate),你需要保存对它的引用以便稍后注销。简单地复制和粘贴相同的代码是行不通的。

关于c# - 当 ThreadPool WaitCallback 在关闭后调用 Form 时,Form 会发生什么情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9557036/

相关文章:

c# - 如何设置ComboBox索引?

.net - 如何更改 MonthCalendar 控件中某些日期的颜色?

c# - RadioButton Click 事件在启动时错误地触发

Java 多线程 - 将数据结构传递给线程

java - 使用 FileLock 在 Java 中锁定文件

c# - 有方法的属性?

c# - 具有多个参数的 WCF Rest GET

c# - ASP.NET MVC : Securing actions based on parameter values

java - wait 和 wait 的时差?

c# - 如何替换字典中的 int 值 C#