我在WPF应用程序中有一些代码如下:
public class MyTextBox : System.Windows.Controls.TextBox, IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
Dispatcher.BeginInvoke((Action) delegate
{
// do work on member variables on the UI thread.
});
}
~MyTextBox()
{
Dispose(false);
}
}
dispose方法永远不会被显式调用,因此析构函数会调用它。看起来在这种情况下,对象将在BeginInvoke中的委托在UI线程上触发之前被销毁。它似乎工作了。这里发生了什么?这样安全吗?
答案 0 :(得分:4)
在这种情况下,似乎对象会在之前被销毁 BeginInvoke中的委托在UI线程上触发
终结器队列工作到UI消息循环。在在UI线程上调用实际委托之前,该对象可能会完成运行其终结器方法,但这并不重要,因为委托无论如何都会排队。
这里发生了什么?
您正在从终结器排队工作到用户界面。
这样安全吗?
安全是一个广义的术语。我会这样做吗?当然不。您从终结器调用UI元素的操作看起来很奇怪,特别是考虑到这是一个TextBox
控件。我建议你完全掌握运行finalizer guarantees并且不保证的内容。首先,运行终结器并不意味着对象会立即在内存中清理。
答案 1 :(得分:3)
当您调用BeginInvoke
时,您需要将一个委托添加到调度程序中的队列,该委托将指向一个对象,该对象具有Dispose
对象的引用被叫了。由于存在对可通过有根变量访问的对象的引用,因此该对象不符合收集条件。
现在,这对使用此代码的其他人来说会非常混乱,因此您应该尽量避免"重新生成"已经完成的对象,如果可能的话。