我在退出范围后遇到了析构函数的问题(它正在调用但是在一段时间之后需要在表单上进行操作,例如更改单选按钮),也许我的代码中存在错误。看看:
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
EventLogger.Print += delegate(string output)
{ if (!textBox1.IsDisposed) this.Invoke(new MethodInvoker(() => textBox1.AppendText(output + Environment.NewLine)), null); };
}
private void button1_Click(object sender, EventArgs e)
{
TestClass test = new TestClass();
}
}
public static class EventLogger
{
public delegate void EventHandler(string output);
public static event EventHandler Print;
public static void AddLog(String TextEvent)
{
Print(TextEvent);
}
}
public class TestClass
{
public TestClass()
{
EventLogger.AddLog("TestClass()");
}
~TestClass()
{
EventLogger.AddLog("~TestClass()");
}
}
}
答案 0 :(得分:9)
是的,因为这不是C ++。在对象离开其声明范围后,不保证立即调用终结器(不是在C ++中的析构函数),当GC决定进入并在您之后清理时调用它。
我可以问你为什么要使用终结器吗?您是否维护对非托管资源的引用,这些资源需要尽可能确定地解除分配(如果是这样,请在IDisposable接口上阅读)? C#终结器的用例很少,实现起来并不常见。
答案 1 :(得分:3)
C#不是C ++。 Destructors don't run synchronously。
您的代码中没有错误,但看起来您可能需要为您的类实现“IDisposable模式”,以便为调用者提供一种方法来保证同步执行某些对象的破坏。
答案 2 :(得分:2)
对于我们这些对C ++模式更熟悉的人来说,查看IDisposable接口的文档很有用:
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
不幸的是,我刚尝试过它并没有按照我的意愿行事。我使用自动对象来保存GUI游标的当前状态,切换到等待游标并在对象超出范围时恢复原始游标。 IDisposable接口确实导致光标被恢复但不是立即 - 因此等待光标显示的时间太长。太糟糕了,因为这是一个非常有用的模式。
答案 3 :(得分:0)
终结器不能在超出范围后立即调用。在对象被垃圾收集时调用它,在超出范围后可以是几毫秒到几天。
终结器不适用于此类代码。它仅用于资源清理。
你不能强迫它在超出范围后立即做某事,但你可以在超出范围之前立即告诉它,使用Close()
或类似的方法来表示对象已完成使用
例如:
private void button1_Click(object sender, EventArgs e)
{
TestClass test = new TestClass();
// do stuff
test.Close();
}
注意:您可以按照建议实现IDisposable
,但这种用法并不完全符合IDisposable
的预期用途,所以尽管它可行,但它有点hackish。