简体   繁体   English

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

[英]Memory leaks in a multi-threaded application using COM & C#

I have written a multi thread unmanaged application which uses COM objects in its worker threads. 我编写了一个多线程非托管应用程序,该应用程序在其工作线程中使用COM对象。 Everything went fine until I started using .NET objects exported as COM to do the work. 一切顺利,直到我开始使用导出为COM的.NET对象来完成工作。

Playing around with the code and commenting out parts of the .NET object functionality I managed to pin it down to the usage of COM objects from within the .NET objects. 试着玩弄代码并注释掉.NET对象功能的某些部分,我设法将其固定为.NET对象中COM对象的用法。 To summarize: 总结一下:

  1. My program starts a couple of worker threads. 我的程序启动了几个工作线程。
  2. Each worker thread initializes a .NET based COM object to do the work. 每个工作线程都会初始化一个基于.NET的COM对象来完成工作。
  3. The .NET based COM objects use unmanaged COM objects internally. 基于.NET的COM对象在内部使用非托管COM对象。

To my surprise the memory consumption of the application started climbing up steadily until OutOfMemory exception started to appear. 令我惊讶的是,直到OutOfMemory异常开始出现之前,应用程序的内存消耗开始稳定增长。

Here is my .NET implementation: 这是我的.NET实现:

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

}

If I comment out this function, the memory leaks disappear. 如果我注释掉此功能,内存泄漏将消失。 If I call GC.Collect() in it the memory leak still happens. 如果我在其中调用GC.Collect(),则仍然会发生内存泄漏。

Any ideas as to what may be going on? 关于可能发生的事情有什么想法吗?

EDIT: Some more info based on comments and answers: 编辑:基于注释和答案的更多信息:

  1. All threads created are running in the MTA. 创建的所有线程都在MTA中运行。
  2. All COM objects implement IMarshal and use the Free Threaded Marshaler. 所有COM对象都实现IMarshal并使用自由线程封送处理程序。
  3. It doesn't matter what do something is - even a int i=0;i++; 做什么是无关紧要的-即使是int i = 0; i ++; generates the leak. 产生泄漏。
  4. The object noted by ComObjetClass is old and tested. ComObjetClass记录的对象是旧的并且经过测试。 This doesn't mean it's not faulty but is not something glaring. 这并不意味着它没有问题,但并不刺眼。
  5. I tried repeatedly creating the COM object from a C# program, both on the main thread and with another created thread. 我尝试通过C#程序在主线程上以及另一个创建的线程上反复创建COM对象。 In both cases the memory leak disappeared. 在这两种情况下,内存泄漏都消失了。 It seems that the cross from unmanaged code to managed and the back again is essential. 从非托管代码到托管代码的交叉似乎又是至关重要的。 Removing any part of it results in the problem disappearing. 删除其中的任何部分都会导致问题消失。

It could be that your COM wrapper objects need to switch to a STA thread to finalize. 可能是您的COM包装对象需要切换到STA线程才能完成。 If your STA doesn't pump messages this will never happen and thus the finalize will never be called which in turn causes the memory leak. 如果您的STA不发送消息,则将永远不会发生,因此将不会调用finalize,这反过来会导致内存泄漏。

There's more info in this KB . 此KB中有更多信息。

Hi would suggest you use following peace of code. 您好建议您使用以下代码。

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

if you are using com object as reference type. 如果您使用com对象作为引用类型。 ex. 恩。 cursor. 光标。 If you are simply doing Marshal.ReleaseComObject(O); 如果您只是在做Marshal.ReleaseComObject(O);

Than it would free only one reference and rest of the reference would be kept inside the memory so better to free all the references. 比仅释放一个引用要多,其余的引用将保留在内存中,因此最好释放所有引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM