Gant
Gant

Reputation: 29889

Is this COM object subject to garbage collection?

I'm using a COM object from .NET using interop. The object basically fetch data from socket and fire some events for .NET layer to process. However, after a while, the COM object stops firing events which revealed later to be because it's collected by GC.

The structure of source code is similar to this one below:

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

What I know so far:

Have I missed some important .NET GC's concepts? Is it possible to obtain the reason for object being GC'd? Is this, possibly, a known GC bug?

I'm using VS 2008 + .NET 3.5 SP1. Appreciate your thoughts. Thanks!

Upvotes: 6

Views: 1968

Answers (3)

Darin Dimitrov
Darin Dimitrov

Reputation: 1038730

No need to use a COM object to reproduce this. Consider the following:

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 it in Release mode and it will exhibit the same behavior. The gen object falls out of scope and is garbage collected because there is nothing to keep it alive during the execution of the loop.

Upvotes: 7

Tim Robinson
Tim Robinson

Reputation: 54734

Your COM objects are eligible for destruction as soon as their .NET equivalents disappear from the program. The last time gen is used is when the ReceiveDataArray += ... call is made.

You should add a call to GC.KeepAlive(gen) at the point in the program where it's acceptable for cleanup to take place. Alternatively, if it needs to stay alive until the program exits, you could add it as a static field.

Upvotes: 2

Martin
Martin

Reputation: 5452

Neither gen nor wr remain active in the Main scope during the execution of your while loop. You enclosed the first three lines in braces which puts those variables in a child scope that is exited before your while loop begins.

Upvotes: 2

Related Questions