假设在 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?或者它会发生什么?
最佳答案
这里有两点:
- 如果您显式处理表单,您可能希望在工作项委托(delegate)执行时引发
ObjectDisposedException
。 - 您的工作项委托(delegate)通过
this
、InvokeRequired
(反过来引用this
)和aButtonOnMyForm 持有对表单的引用
。因此,只要ThreadPool
线程尚未完成执行,您的表单就没有资格进行垃圾回收。这就是代码不会崩溃的原因。 (注意:无论如何,this
始终是隐式可访问的。)
由此得出的另一件事是,通常明智的做法是在表单关闭之前从表单中注销外部事件处理程序,以免造成内存泄漏。如果你注册了一个 lambda 表达式或匿名委托(delegate),你需要保存对它的引用以便稍后注销。简单地复制和粘贴相同的代码是行不通的。
关于c# - 当 ThreadPool WaitCallback 在关闭后调用 Form 时,Form 会发生什么情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9557036/