C # FileLogTraceListener выдает исключение при закрытии - PullRequest
1 голос
/ 18 октября 2011

Это класс ведения журнала с конструктором:

public QFXLogger(
        int maxFileSize,
        TraceLevel logLevel)
    {
        this.maxFileSize = maxFileSize;
        logSwitch.Level = logLevel;
        //Configure log listener
        traceListener = new FileLogTraceListener();
        traceListener.DiskSpaceExhaustedBehavior = DiskSpaceExhaustedOption.DiscardMessages;
        traceListener.CustomLocation = @".\Log";
        traceListener.BaseFileName = "QFXLog";
        traceListener.AutoFlush = true;
        //Remove all other listeners
        Trace.Listeners.Clear();
        //Add QFX listener
        Trace.Listeners.Add(traceListener);
        //Write header
        WriteSessionHeader();
    }

А это деструктор:

~QFXLogger()
    {
        WriteSessionFooter();
        traceListener.Close();
    }

Я просто хочу записать нижний колонтитул в базовый поток, прежде чем регистратор получит GC. Без деструктора все хорошо, но с ним я получаю следующее:

Unhandled Exception: System.ObjectDisposedException: Cannot access a closed file
.
at System.IO.__Error.FileNotOpen()
at System.IO.FileStream.Flush(Boolean flushToDisk)
at System.IO.FileStream.Flush()
at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
at System.IO.StreamWriter.Flush()
at Microsoft.VisualBasic.Logging.FileLogTraceListener.ReferencedStream.CloseS
tream()
at Microsoft.VisualBasic.Logging.FileLogTraceListener.CloseCurrentStream()
at Microsoft.VisualBasic.Logging.FileLogTraceListener.Write(String message)
at System.Diagnostics.TraceInternal.Write(String message)
at System.Diagnostics.Trace.Write(String message)
at QFXShell.QFXLogger.WriteSessionFooter()
at QFXShell.QFXLogger.Finalize()

Мне кажется, что основной поток уже закрыт.

Как я могу подавить это закрытие (основного потока) или это другая проблема?

Ответы [ 2 ]

2 голосов
/ 18 октября 2011

Финализаторы (деструкторы) в c # не должны использоваться в этом методе.Финализаторы предназначены только для для освобождения неуправляемых ресурсов.Когда вызывается финализатор, доступ к другим объектам .net не гарантируется , и он должен высвобождать только неуправляемые ресурсы, которые были выделены вами напрямую.

Операции финализации имеют следующие ограничения:

  • Финализаторы двух объектов не гарантированно работают в каком-либо определенном порядке, даже если один объект ссылается на другой.То есть, если Объект A имеет ссылку на Объект B и оба имеют финализаторы, Объект B, возможно, уже был завершен, когда запускается финализатор Объекта А.

Что вам нужно сделать, это реализовать IDisposable Interface , чтобы правильно закрыть файл журнала.Некоторая дополнительная информация может быть найдена в IDisposable и сборке мусора Kelly Leahy .

Если вы не в ситуации, когда поможет одноразовый класс (глобальный объект и т. Д.), Вы всегда можете реализоватьClose метод, чтобы убедиться, что файл действителен перед его выпуском.

1 голос
/ 18 октября 2011

Слишком поздно для вас закрыть объект трассировки в деструкторе.В этот момент уже могут быть удалены многие ненужные объекты.

Я бы предложил реализовать интерфейс IDisposable с открытым методом Dispose и вызывать этот метод, как только вы узнаете, что выэтот объект QFXLogger больше не понадобится.В этом методе Dispose я проверю, не является ли объект трассировки NULL, открытым, а затем я вызову Close для него.

См. Правильное использование интерфейса IDisposable для получения дополнительной информации.

...