c# - 此 COM 对象是否需要进行垃圾回收?

标签 c# .net com garbage-collection com-interop

我正在使用 .NET 中的 COM 对象并使用互操作。该对象基本上从套接字获取数据并触发一些事件供 .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
}

alt text

目前我所知道的:

  • 据我了解,对象 gen 不应以任何方式进行垃圾回收。因为该对象在 Main 中仍然处于事件状态 范围。但是目前的结果显示该对象被GC回收了。

  • 只有当构建为发布并运行而不调试时,对象才会被垃圾回收。在调试器下运行调试构建/运行两种模式都很好。

  • 程序将在第一个 Gen #0 集合之后精确地打印第一个“False”。

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

  • 通过添加 Program 类的另一个静态字段来保留它的引用,也可以防止它被 GC。

  • 尝试不同的数据负载,我发现 GC 仅在私有(private)字节数超过 ~ 3X MB 的阈值时收集对象。

  • 检查 CLRProfiler ,提到的对象被怀疑是 GC。

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

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

最佳答案

无需使用 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()
    {
    }
}

在 Release模式下运行它,它会表现出相同的行为。 gen 对象超出范围并被垃圾收集,因为在循环执行期间没有任何东西可以使它保持事件状态。

关于c# - 此 COM 对象是否需要进行垃圾回收?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4757869/

相关文章:

c# - 如何让 C# 项目忽略程序集的版本号?

c# - 生成链接时如何忽略当前路由值?

C# 用户定义的异常未被捕获

C# COM 类 - DISP_E_UNKNOWNNAME

c# - 使用 NEST/Elasticsearch.Net 执行原始 JSON 请求

c# - 如何制作非矩形Winform?

c# - 我如何能够更改类外的私有(private)只读数组内的值?

c# - 迭代器变量是否有单数形式与复数形式相同的命名准则?

c++ 中的 C# COM 互操作

c# - 如何从 C# 调用 native 库?