简体   繁体   中英

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. Everything went fine until I started using .NET objects exported as COM to do the work.

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. 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.
  3. The .NET based COM objects use unmanaged COM objects internally.

To my surprise the memory consumption of the application started climbing up steadily until OutOfMemory exception started to appear.

Here is my .NET implementation:

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.

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.
  2. All COM objects implement IMarshal and use the Free Threaded Marshaler.
  3. It doesn't matter what do something is - even a int i=0;i++; generates the leak.
  4. The object noted by ComObjetClass is old and tested. 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. 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. 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.

There's more info in this 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. ex. cursor. If you are simply doing 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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