Есть ли какие-либо события, которые сообщают приложению, когда произошла сборка мусора? - PullRequest
4 голосов
/ 07 марта 2009

Я пытаюсь найти способ узнать о сборке мусора. Либо, когда он начался, закончился или находится в процессе. Мне действительно нужно какое-то событие, связанное с самой коллекцией (я думаю).

Моя проблема в том, что у меня есть WeakEventManager (написанный с нуля), и у меня есть методы очистки, которые удаляют и WeakReferences, которые больше не существуют (WeakReferences находятся в словаре).

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

Ответы [ 5 ]

7 голосов
/ 07 марта 2009

Класс System.GC предлагает метод RegisterForFullGCNotification, который позволяет создавать уведомления, когда сборка мусора будет завершена и когда она будет завершена.

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

Пожалуйста, смотрите следующие ссылки для полной информации:

Уведомления о вывозе мусора

GC.RegisterForFullGCNotification Method

7 голосов
/ 07 марта 2009

Вы можете отслеживать объект счетчика производительности .NET Memory. Есть подсчеты количества поколений 0, 1 и 2 коллекций.

Как правило, в системе, основанной на GC, прямая ссылка на GC является чем-то вроде анти-паттерна. Вы, вероятно, (учитывая ограниченное описание) лучше просто лениво очистить, когда попытаетесь использовать очищенную WeakReference.

4 голосов
/ 07 марта 2009

Вот класс, который я использовал для входа в SmartInspect, который произошел с GC. Вы легко сможете изменить то, что делает этот класс.

Чтобы начать, просто позвоните GCLog.Register();.

#region File Header
// This file Copyright © 2007 Lasse Vågsæther Karlsen, All rights reserved.
//
// $Id: GCLog.cs 135 2008-05-28 11:28:37Z lassevk $
#endregion

#region Using

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Gurock.SmartInspect;

#endregion

namespace PresentationMode
{
    /// <summary>
    /// This class is used to get a running log of the number of garbage collections that occur,
    /// when running with logging.
    /// </summary>
    public sealed class GCLog
    {
        #region Construction & Destruction

        /// <summary>
        /// Releases unmanaged resources and performs other cleanup operations before the
        /// <see cref="GCLog"/> is reclaimed by garbage collection.
        /// </summary>
        ~GCLog()
        {
            SiAuto.Main.LogMessage("GARBAGE COLLECTED");
            if (!AppDomain.CurrentDomain.IsFinalizingForUnload() && !Environment.HasShutdownStarted)
                new GCLog();
        }

        #endregion

        #region Public Static Methods

        /// <summary>
        /// Registers this instance.
        /// </summary>
        public static void Register()
        {
#if DEBUG
            if (SiAuto.Si.Enabled)
                new GCLog();
#endif
        }

        #endregion
    }
}
1 голос
/ 07 марта 2009

Если вы создаете одноразовый объект, который имеет исходящую ссылку на ваши объекты, но не имеет входящих ссылок, т.е.

new MyGcMonitor(this);  // don't store result

И если вы убедитесь, что в MyGcMonitor есть Finalizer (деструктор), то этот финализатор будет вызван после завершения процесса GC в отдельном потоке. Финализатор может вызвать метод, чтобы сообщить, что ваш класс завершен.

Самое сложное, если вам это нужно снова, например, если вы решили не освобождать свой объект. Затем вам нужно настроить последовательность, которая вне запущенного потока GC создает другой экземпляр MyGcMonitor. Я полагаю, вы могли бы использовать Delegate.invoke и в этом делегате сначала вызовите GC.WaitForPendingFinalizers ().

В случае воскрешения MyGcMonitor возникнет аналогичная проблема, связанная с удалением (статической) ссылки в дальнейшем.

0 голосов
/ 20 марта 2014

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

    private static bool NeedsCleaning ()
    {
        if (DummyRef.IsAlive) {
            return false;
        }
        DummyRef = new WeakReference (new object ());
        return true;
    }
...