在垃圾收集发生时是否有任何事件告诉应用程序?

时间:2009-03-07 18:36:19

标签: c# events garbage-collection

我正试图找到一种了解垃圾收集的方法。当它已经开始,完成或正在进行时。我真的只需要一些与集合本身相关的事件(我认为)。

我的问题是我有一个WeakEventManager(从头开始编写),我有清除方法,删除和WeakReferences不再存在(WeakReferences在字典中)。

问题是我必须知道何时“清理”。当收集器正在做它的事情时清理它会很好。即使它是在垃圾收集之后,至少下一个集合将删除这些旧对象。

5 个答案:

答案 0 :(得分:7)

您可以监视.NET内存性能计数器对象。对于0,1和2集合的数量有计数。

通常在基于GC的系统上,直接引用GC是一种反模式。当您尝试使用已清除的WeakReference时,您可能(给出有限的描述)只是懒得清理。

答案 1 :(得分:7)

System.GC类提供了一个RegisterForFullGCNotification方法,该方法允许在垃圾收集即将完成时以及完成垃圾收集时引发通知。

这并不理想,因为使用此方法有一些注意事项,例如必须禁用并发垃圾收集才能使此方法起作用。

请参阅以下链接以获取完整信息:

Garbage Collection Notifications

GC.RegisterForFullGCNotification Method

答案 2 :(得分:4)

这是我用来登录到GC发生的SmartInspect的类。您应该可以轻松地更改此课程的内容。

要开始使用,只需致电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
    }
}

答案 3 :(得分:1)

如果您创建一个抛弃对象,该对象具有对象的传出引用但没有传入引用,即

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

如果确保MyGcMonitor有一个Finalizer(析构函数),那么在GC fase完成之后,将在一个单独的线程上调用该终结器。 终结器可以调用一个方法来告诉你的类完成完成。

棘手的部分是如果你再次需要它,例如你决定不释放你的物体。然后,您必须设置一个序列,该序列在运行的GC线程之外创建另一个MyGcMonitor实例。我想你可以使用delegate.invoke并在该委托中首先调用GC.WaitForPendingFinalizers()。

重新启动MyGcMonitor会有类似的问题,即稍后删除(静态)引用。

答案 4 :(得分:0)

在优先级较低的线程中,您可以使用这种简单的静态方法检查应用程序是否需要清理。

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