使用COM& A的多线程应用程序中的内存泄漏C#

时间:2009-03-13 10:00:55

标签: c# multithreading com interop memory-leaks

我编写了一个多线程非托管应用程序,它在其工作线程中使用COM对象。一切都很顺利,直到我开始使用导出为COM的.NET对象来完成工作。

使用代码并注释掉.NET对象功能的一部分,我设法将其归结为.NET对象中COM对象的使用。总结一下:

  1. 我的程序启动了几个工作线程。
  2. 每个工作线程初始化一个基于.NET的COM对象来完成工作。
  3. 基于.NET的COM对象在内部使用非托管COM对象。
  4. 令我惊讶的是,应用程序的内存消耗开始稳步攀升,直到OutOfMemory异常开始出现。

    这是我的.NET实现:

    void DoSomeWork()
    {
        IComObject O = new ComObjectClass();
        try
        {
            // do something
        }
        finally
        {
            Marshal.ReleaseComObject(O);
        }
    
    }
    

    如果我注释掉这个功能,内存泄漏就会消失。如果我在其中调用GC.Collect(),内存泄漏仍然会发生。

    关于可能发生的事情的任何想法?

    编辑:根据评论和答案提供更多信息:

    1. 创建的所有线程都在MTA中运行。
    2. 所有COM对象都实现了IMarshal并使用Free Threaded Marshaler。
    3. 无论做什么都没关系 - 即使是int i = 0; i ++;产生泄漏。
    4. ComObjetClass注意到的对象已经过旧并经过测试。这并不意味着它没有错,但并不是明显的东西。
    5. 我尝试在主线程和另一个创建的线程上重复从C#程序创建COM对象。在这两种情况下,内存泄漏都消失了。似乎从非托管代码到托管和后台的交叉是必不可少的。删除它的任何部分会导致问题消失。

2 个答案:

答案 0 :(得分:2)

可能是您的COM包装器对象需要切换到STA线程来完成。如果你的STA没有泵送消息,这将永远不会发生,因此永远不会调用finalize,从而导致内存泄漏。

this KB中有更多信息。

答案 1 :(得分:0)

您建议您使用以下代码安静。

     if (feature != null) 
        { 
            while (Marshal.ReleaseComObject(feature) > 0) 
            { }
            feature=null;
        }

如果您使用com对象作为引用类型。恩。光标。 如果你只是在做      对Marshal.ReleaseComObject(O);

它只释放一个引用,其余的引用将保留在内存中,以便更好地释放所有引用。