此COM对象是否受垃圾回收?

Gan*_*ant 6 .net c# com garbage-collection com-interop

我正在使用来自.NET的COM对象使用互操作.该对象基本上从socket获取数据并触发一些事件以供.NET层处理.但是,过了一段时间后,COM对象会停止触发事件,这些事件后来显示是因为它是由GC收集的.

源代码的结构类似于下面这个:

static void Main(string[] args)
{
    MyEventGen gen = new MyEventGen();
    WeakReference wr = new WeakReference(gen);
    gen.ReceiveDataArray += 
            new _IMyEventGenEvents_ReceiveDataArrayEventHandler(gen_ReceiveDataArray);
    while (true)
    {
        Thread.Sleep(1000);
        Console.WriteLine(wr.IsAlive);
    }
}

static void gen_ReceiveDataArray(ref Array indices, ref Array values)
{
    // do nothing
}
Run Code Online (Sandbox Code Playgroud)

替代文字

到目前为止我所知道的:

  • 据我所知,对象gen不应该以任何方式进行垃圾收集.由于对象在Main范围内仍处于活动状态.但到目前为止的结果表明该对象是由GC收集的.

  • 该对象仅在构建为Release时进行垃圾收集,并且无需调试即可运行.在调试器下运行Debug构建/运行两种模式都可以.

  • 该程序将在第一代Gen#0 Collection之后精确打印第一个"False" .

  • 通过访问while循环中的对象,例如Console.WriteLine(gen.ToString()),防止它被GC'd!

  • 通过添加另一个Program类的静态字段来保持其引用也阻止它来自GC'd.

  • 尝试使用不同的数据负载,我发现GC只在Private Bytes达到~3X MB的阈值时收集对象.

  • 使用CLRProfiler进行检查时,提到的对象被GC'd怀疑.

我是否错过了一些重要的.NET GC概念?是否有可能获得对象GC'd的原因?这可能是一个已知的GC错误吗?

我正在使用VS 2008 + .NET 3.5 SP1.欣赏你的想法.谢谢!

Dar*_*rov 7

无需使用COM对象来重现这一点.考虑以下:

public class MyEventGen
{
    public event Action ReceiveDataArray;
}

class Program
{
    public static void Main()
    {
        var gen = new MyEventGen();
        var wr = new WeakReference(gen);
        // this is the last time we access the 
        // gen instance in this scope so after this line it
        // is eligible for garbage collection
        gen.ReceiveDataArray += new Action(gen_ReceiveDataArray);

        // run the collector
        GC.Collect();
        while (true)
        {
            Thread.Sleep(1000);
            Console.WriteLine(wr.IsAlive);
        }
    }

    static void gen_ReceiveDataArray()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

在发布模式下运行它将表现出相同的行为.该gen对象超出范围并被垃圾收集,因为在执行循环期间没有任何东西可以使它保持活动状态.