Kugel
Kugel

Reputation: 19844

Can running object be garbage collected?

I have a simple class:

public class Runner
{
    public void RunAndForget(RunDelegate method)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(Run), method);
    }

    private void Run(object o)
    {
        ((RunDelegate )o).Invoke();
    }
}

And if I use this like so:

private void RunSomethingASync()
{
    Runner runner = new Runner();
    runner.FireAndForget(new RunDelegate(Something));
}

Is there any danger using it like this? My C++ guts tell me that runner object should be destroyed after RunSomethingASync is finished. Am I right? What happens then to the method running on different thread?

Or perhaps it is other way around and runner will not be collected? That would be a problem considering I may call RunSomethingASync() many times.

Upvotes: 1

Views: 273

Answers (3)

kemiller2002
kemiller2002

Reputation: 115498

The object will not be garbage collected until it is no longer rooted - that is, until all reachable references to it have been removed. There is an exception to this where if two objects hold references to each other and nothing else holds references to those objects, those two objects are available for Garbage Collection. Running asynchronous methods like yours holds references to the object and won't be disposed mid call.

A note to a comment below: Calling Dispose() on a method does not force a Garbage Collection on that object.

Since we're talking about Garbage Collection here is a link to the GC.Collect function: http://msdn.microsoft.com/en-us/library/xe0c2357.aspx

and the GC class itself:
http://msdn.microsoft.com/en-us/library/a0fwz4wc(v=VS.100).aspx

EDIT: See Adam's answer about delegates and references to objects.

Upvotes: 5

Adam Robinson
Adam Robinson

Reputation: 185643

My C++ guts tell me that runner object should be destroyed after RunSomethingASync is finished. Am I right?

In short, no. .NET garbage collection is not done on a deterministic basis. An object is eligible for garbage collection once it is no longer rooted - that is, once no more reference paths to it (from living objects) exist. There is no guarantee that any particular object -- or, indeed, any object at all -- will ever be garbage collected, though it's pretty likely.

However, in your case, your object isn't even eligible. While the object is falling out of scope in your code (so it would appear that no references exist), delegates do contain references to their owning instance (assuming they point to an instance method). A reference to your object will exist until Run is called, as the ThreadPool is holding on to a reference to the delegate until then, and that delegate has a reference to Runner.

So, to answer your question, there is no danger in what you're doing. Because the delegate references the instance, your object cannot and will not be collected until after your operation completes. Once it completes, your object will then be eligible.

Upvotes: 8

TcKs
TcKs

Reputation: 26632

No, object where's is code running can not be collected because, there is several references to the object (for example "this" is reference to the object).

Upvotes: 0

Related Questions