C#:收集WeakReference之前的通知?

Rob*_*ser 10 .net c# events garbage-collection weak-references

在C#/ .NET中,有没有办法在弱引用指向的对象被破坏之前获得通知?基本上,我想允许收集一个对象,但是在对象被销毁之前做一些事情,而不修改代码来添加析构函数(因为我不知道究竟什么类型的对象将被我的代码起诉).

谢谢,罗伯特

Reu*_*ass 9

.Net 4.0有你需要的解决方案:ConditionalWeakTable.这是一个简短的程序,展示了这个想法.(这里也讨论过)

using System;
using System.Runtime.CompilerServices;

namespace GCCollectNotification
{
    class ObjectToWatch { }

    class Notifier
    {
        public object ObjectToWatch { get; set; }
        ~Notifier() { Console.WriteLine("object is collected"); }
    }

    class Program
    {
        private ConditionalWeakTable<object, Notifier> map
            = new ConditionalWeakTable<object, Notifier>();

        public void Test()
        {
            var obj = new ObjectToWatch();
            var notifier = map.GetOrCreateValue(obj);
            notifier.ObjectToWatch = obj;
        }

        static void Main(string[] args)
        {
            new Program().Test();

            GC.Collect();
            GC.WaitForPendingFinalizers();

            // "object is collected" should have been printed by now

            Console.WriteLine("end of program");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Jar*_*Par 6

没有办法实现这个功能.

经过一番猜测后,我认为不可能以您描述的方式实现某个功能.

考虑到收集WeakReference持有的对象时,没有更多的引用(因此它是可收集的).对于对您有用的事件,它需要提供对象作为事件的一部分.这意味着引用已从可收集到不可收集.没有什么能阻止处理代码重新获得对该对象的引用.因此,该对象不再被视为可收集.CLR需要在对象上进行第二次传递以重新确保它是可收集的.

您可以看到第二次无法引发事件,因为它会导致无法收集的对象.

声称在收集对象之前引发此事件将是对命名的误用.只是因为任何处理程序都可以通过建立对对象的新引用来阻止收集它.相反,它必须是"ObjectMaybeAboutToBeCollected".这可能不会给你你正在寻找的行为.


mfa*_*mkh 6

你不能这样做.但是,您可以做的是观察GC何时接近(CLR v3.5Sp1中有新的GC API允许您这样做,GCNotifications)