3

超出范围后我的析构函数有问题(它正在调用但经过一段时间后需要对表单进行操作,例如更改单选按钮),也许我的代码有错误。看一看:

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()");
        }
    }

}
4

4 回答 4

9

对,因为这不是 C++。终结器(不是 C++ 中的析构函数)不能保证在对象离开其声明范围后立即被调用,当 GC 决定突袭并在你之后清理时调用它。

我可以问你为什么要使用终结器开始吗?您是否维护对需要尽可能确定地释放的非托管资源的引用(如果是,请在 IDisposable 接口上阅读)?C# 终结器的用例很少而且相差甚远,实现它们并不常见。

于 2012-06-11T17:52:06.083 回答
3

C# 不是 C++。析构函数不会同步运行

您的代码中没有错误,但看起来您可能需要为您的类实现“IDisposable 模式”,以便为调用者提供一种方法来保证您的对象的某些破坏是同步执行的。

于 2012-06-11T17:54:46.940 回答
2

对于我们这些更熟悉 C++ 模式的人来说,查看 IDisposable 接口的文档很有用:

http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

不幸的是,我刚刚尝试过它并没有按我的意愿工作。我使用了一个自动对象来保存 GUI 光标的当前状态,切换到等待光标并在对象超出范围时恢复原始光标。IDisposable 界面确实会导致光标被恢复但不是立即恢复 - 因此等待光标显示时间过长。太糟糕了,因为这是一个非常有用的模式。

更新:一段时间后,C# try/finally 模式就足够舒适了:

public void do_something_time_consuming()
{
   ShowBusyCursor cursor = new ShowBusyCursor();

   try
   {
      ...
      return;
   }
   finally
   {
      cursor.done();
   }
}
于 2013-10-30T20:51:03.387 回答
0

终结器并非设计为在超出范围后立即调用。当对象被垃圾收集时调用它,这可能是在超出范围后的几毫秒到几天的任何时间。

终结器不适用于此类代码。它仅用于资源清理。

您不能强制它在超出范围后立即执行某些操作,但您可以在超出范围之前立即告诉它,使用Close()或类似的方法表示对象已完成使用。

例如:

private void button1_Click(object sender, EventArgs e)
{
    TestClass test = new TestClass();
    // do stuff
    test.Close();
}

注意:您可以IDisposable按照建议实现 ,但这种用法并不完全符合 的预期用途IDisposable,因此虽然它可以工作,但它有点 hackish。

于 2012-06-11T18:03:03.230 回答