是不是保证完成运行的析构函数?

Ste*_*ris 7 c# destructor finalizer

析构函数很奇怪.我试图通过使用"智能"参考管理来消除使用一次性模式的需要,确保垃圾收集器可以在正确的时间收集对象.在我的一个析构函数中,我不得不等待来自另一个对象的事件,我注意到它没有.应用程序只是关闭,析构函数在执行过程中被终止.我希望总是允许析构函数完成运行,但是下面的测试表明这不是真的.

using System;
using System.Diagnostics;
using System.Threading;


namespace DestructorTest
{
    class Program
    {
        static void Main( string[] args )
        {
            new DestructorTest();
            new LoopDestructorTest();
            using ( new DisposableTest() ) { }
        }
    }

    class DestructorTest
    {
        ~DestructorTest()
        {
            // This isn't allowed to finish.
            Thread.Sleep( 10000 );
        }       
    }

    class LoopDestructorTest
    {
        ~LoopDestructorTest()
        {           
            int cur = 0;
            for ( int i = 0; i < int.MaxValue; ++i )
            {
                cur = i;
            }
            // This isn't allowed to finish.
            Debug.WriteLine( cur );
        }
    }

    class DisposableTest : IDisposable
    {
        public void Dispose()
        {
            // This of course, is allowed to finish.
            Thread.Sleep( 10000 );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么,是不是保证完成运行的析构函数?

Jon*_*eet 16

那么,是不是保证完成运行的析构函数?

不.从我记忆中来看,当进程终止时,它会给终结器几秒钟的执行时间,然后突然终止进程.你不会想要一个糟糕的终结器来阻止一个进程完成,是吗?

您应该将最终确定视为"尽力而为"的清理 - 特别是,在整个系统突然关闭的情况下,例如BSOD或停电,情况不会发生.

编辑:我从Joe Duffy博客文章中找到了一些伪文档:

如果在停止所有正在运行的线程的过程中锁被孤立,则关闭代码路径将无法获取锁.如果这些采集是在非超时(或长时间超时)获取的情况下完成的,则会发生挂起.为了解决这个问题(以及可能发生的任何其他类型的挂起),CLR会发出一个看门狗线程来监视终结器线程.虽然可配置,但默认情况下CLR会让终结器在变得不耐烦之前运行2秒; 如果超过此超时,则终止终结器线程,并且继续关闭而不会耗尽终结器队列的其余部分.

  • @StevenJeuris:听起来你在真正*不应该*的情况下依赖终结者.终结者应该*帮助*以避免资源泄漏 - 如果你的系统没有完成运行会导致系统状态不佳,你应该重新设计.毕竟,由于BSOD,停电等原因,它们总是有可能不会*运行. (6认同)