Разве деструкторам не гарантировано закончить работу? - PullRequest
7 голосов
/ 30 марта 2012

Деструкторы странные .Я пытался устранить необходимость использования одноразового шаблона с помощью «умного» справочного управления, гарантирующего, что сборщик мусора сможет собирать объекты в нужное время.В одном из моих деструкторов мне пришлось ждать события от другого объекта, который я заметил, что это не так.Приложение просто закрылось, и деструктор был прерван в середине выполнения.Я ожидаю, что деструктору всегда разрешено завершать работу, но, как показывает следующий тест, это не так.

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

Итак, разве деструкторам не гарантированно завершается работа?

Ответы [ 4 ]

16 голосов
/ 30 марта 2012

Итак, разве деструкторам не гарантированно завершится работа?

Нет.Из того, что я помню, когда процесс завершается, он дает финализаторам пару секунд для выполнения, но затем завершает процесс внезапно.Вы бы не хотели, чтобы плохой финализатор препятствовал завершению процесса, не так ли?

Вы должны рассматривать финализацию как очистку с "максимальными усилиями" - в частности, это , а не произойдет в ситуациях, когда вся система будет внезапно закрыта, таких как BSOD или отключение питания.

РЕДАКТИРОВАТЬ: я нашел некоторую псевдодокументацию в виде сообщения в блоге от Джо Даффи:

Если в процессе остановки всех запущенных потоков была потеряна блокировка, то путь кода завершения работы не сможет получить блокировку.Если эти приобретения сделаны с приобретениями без тайм-аута (или с длительным тайм-аутом), произойдет зависание.Чтобы справиться с этим (и любым другим типом зависания, которое может произойти), CLR анонсирует сторожевой поток, чтобы следить за потоком финализатора.Хотя конфигурируемо, по умолчанию CLR позволяет финализаторам работать в течение 2 секунд, прежде чем наступит нетерпение;Если этот тайм-аут превышен, поток финализатора останавливается, и завершение работы продолжается, не истощая оставшуюся очередь финализатора.

1 голос
/ 30 марта 2012

.NET не поставляется с деструкторами. Ваш код содержит финализаторы вместо.

Финализаторы вызываются, когда объект собирается мусором, а не когда он обнуляется. Они также получают ограниченное время выполнения для предотвращения зависания объектов.

См. Также https://en.wikipedia.org/wiki/Finalizer.

1 голос
/ 30 марта 2012

Итак, разве деструкторам не гарантированно завершится работа?

Хотя этого нет в вашем коде, могут быть случаи, когда GC.SuppressFinalize явно вызываетсяиз Dispose() метода.Это подавляет финализацию и относится к объектам, которые этого не требуют.

Это может значительно улучшить производительность, так как финализируемые объекты всегда будут выживать при одной сборке мусора, то есть будут переведены в G1 поколения или даже в G2 поколения, что связано с большими затратами.

0 голосов
/ 20 августа 2015

Другой способ взглянуть на то, что финализаторы вызываются, когда сборщик мусора освобождает память.

Однако, если у вас была программа, которая требовала максимум 1 МБ памяти, но работала на машине с 10 МБ памяти, то правильной реализацией сборщика мусора было бы ничего не делать (так как для этой программы было бы достаточно памяти). выполнение). В этом случае финализаторы никогда не будут вызваны.

...