Почему моя функция не вызывается?

 class Program : CriticalFinalizerObject
    {
        static void Main(string[] args)
        {

            Program p = new Program();
            TextWriterTraceListener listener = new TextWriterTraceListener(@"C:trace.txt");
            Trace.Listeners.Clear(); // Remove default trace listener
            Trace.Listeners.Add(listener);
            Trace.WriteLine("First Trace"); // Generate some trace messages
            Trace.WriteLine("Perhaps last Trace.");

        }

        ~Program()
        {
            Trace.Close();
        }
    }

Я получаю размер файла =0

в finilizer должны казнили, потому что я получаю от CriticalFinalizerObject

Я не хочу использовать Trace.Close () не в Финализаторе.

редактировать

после @eric Lippert ответ : Ive отредактировал код, пытаясь сопоставить его с:область ограниченного выполнения ( но все равно нет успех)

  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    class Program : CriticalFinalizerObject
    {

        static void Main(string[] args)
        {
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
            }
            catch (Exception e)
            {
            }
            finally
            {
                Program p = new Program();
                TextWriterTraceListener listener = new TextWriterTraceListener(@"C:trace1.txt");
                Trace.Listeners.Clear();
                Trace.Listeners.Add(listener);
                Trace.WriteLine("First Trace");
                Trace.WriteLine("Perhaps last Trace.");
            }
        }

        ~Program()
        {
            Trace.Flush();
        }
    }

3 ответов


как четко указано в документации:

в классах, производных от класса CriticalFinalizerObject, общеязыковая среда выполнения (CLR) гарантирует, что всему критическому коду завершения будет предоставлена возможность выполнить, при условии, что финализатор следует правилам для CER, даже в ситуациях, когда среда CLR принудительно выгружает домен приложения или прерывает поток. Если финализатор нарушает правила для CER, это может быть не успешно выполнить

выполняет ли ваш финализатор все правила для ограниченной области выполнения?

обновление:

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

  • выделить память!--16-->
  • поле тип значения
  • получить блокировку
  • вызовите произвольный виртуальный метод
  • вызовите любой метод, которому не хватает контракта надежности

делает ли ваш финализатор какую-либо из этих пяти вещей? Если это так, то нет требования, чтобы CLR уважал ваше желание, чтобы финализатор всегда работал.

более того: забудьте о ограниченных регионах выполнения на мгновение, потому что ваша программа как стенды теперь даже не threadsafe. Вы вписали в программу отвратительное состояние расы.

Что останавливает дрожание от сбора мусора p до трассировка начнется? Ничего! Дрожание знает, что p никогда не будет использоваться снова, и совершенно в своих правах собирать его сразу после его распределения. Может быть, это флеш!--33-->в любое время в потоке финализатора, включая до запись трассировки происходит, или в центре любого из них.


потому что вы не создали экземпляр класса Program.

вы можете подробнее здесь:

этот метод автоматически вызывается после того, как объект становится недоступным, если только объект не был освобожден от завершения вызовом SuppressFinalize. Во время завершения работы домена приложения Finalize автоматически вызывается для объектов, которые не освобождены от завершения, даже тех, которые все еще доступны. Завершить автоматически вызывается только один раз в данном экземпляре, если объект не перерегистрирован с помощью механизма, такого как ReRegisterForFinalize и GC.SuppressFinalize впоследствии не вызывался.

Итак, вам нужно иметь экземпляр объекта, если вы хотите, чтобы finilizer был вызван.

UPDATE: рассмотрите возможность использования Trace.AutoFlush = true; Если вы хотите, чтобы сообщение было написано.

UPDATE: (почему функция Close не вызывается?) На самом деле вы закрываете функцию (если ничего исключительного не происходит в других финализаторы). Если вы сохраните TraceListener по умолчанию (remove Trace.Listeners.Clear() call), вы увидите, что все строки успешно записаны в окно вывода.

проблема здесь в том, что StreamWriter (который создается внутри TextWriterTraceListener) не имеет финализатора. Таким образом, он не сбрасывает все данные в файл. Что нужно сделать:

FileStream file = new FileStream(@"C:\trace.txt", FileMode.OpenOrCreate);
StreamWriter writer = new StreamWriter(file);
GC.SuppressFinalize(file);
GC.SuppressFinalize(file.SafeFileHandle);
var listener = new TextWriterTraceListener(writer);

на самом деле вам нужно будет закрыть файл вручную на вашем финализаторе.


В C# вы не можете быть уверены, когда или что ваш финализатор вызывается, потому что GC обрабатывает это. Поэтому, если у вас есть некоторые ресурсы для выпуска, лучше всего создать класс, который реализует IDisposable и используйте его так:

using (MyResourceHolder rh = new MyResourceHolder()) {
    // ...
} // rh.Dispose() is called implicitly

в Dispose-методе вы можете вызвать Trace.Close().

см.http://msdn.microsoft.com/en-us/library/system.idisposable.aspx для хорошей реализации IDisposable.