Re: Threads & Garbage Collection

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance

From: J.Marsch (jeremy_at_ctcdeveloper.com)
Date: 04/27/04


Date: Tue, 27 Apr 2004 11:53:08 -0500

Martin:

I'm not sure that the behavior that you are seeing affects Garbage
collection as a whole -- rather, just the object that owns the method that
the thread runs.

1 fact that might interest you: Even in unmanaged applications (like C++ or
Delphi), if you let a thread "run away", without exiting it, it will hold
your process open.

Now, here's what I _think_ is going on in .Net: (why your object stays
alive):
Your object encapsulates the thread, right? So, the delegate that you
passed to the System.Thread's constructor is an instance member of your
manager object object, right?

A delegate contains a member called Target. Target is a reference to the
object that has the method that is being invoked by the delegate. So, when
you construct the thread, and you pass it a ThreadStart delegate, you are
giving out a reference to your object. So, there is no (or very little)
magic going on here. If I were going to place bets, I'd guess that it goes
something like this:

You have an O/S thread that is alive. It somehow keeps alive a reference to
the System.Threading.Thread object that manages it (this part might be
magic, but I though that I read somewhere that a reference to the Thread
Object is put in TLS on the thread that it manages). The thread object
holds a reference to a delegate (your ThreadStart delegate), which, in turn,
references your management object (through the Target property).

If that's right, there is no special GC behavior going on, there is just a
valid reference to your management object until the thread goes away. So,
your object is held in memory.

Facts vs hypothesis:

Fact: I know for a fact that a delegate will hold its target (the owner of
the method that will be invoked) in memory. This is well tested, documented
behavior.

Fact: I know that you hand a delegate to the Thread object in the
constructor.

Hypothesis: It's pretty likely that the Thread Object holds on to your
delegate for its lifetime. Therefore the target object cannot be eligible
for collection until the Thread object is eligible for collection

Hypothesis: I'm pretty sure that the ThreadObject is kept alive at least
until thread that it manages exits (I'm basically positive of this, but I
haven't decompiled the code, so I won't call it a fact);

Conclusion: The System.Thread stays alive until the thread is exited. The
System.ThreadObject holds reference to your management object (through a
delegate). So, your management object cannot be released from memory until
the thread exits.

"Martin Maat" <dummy@somewhere.nl> wrote in message
news:108sg684n9rd4ce@corp.supernews.com...
> I am puzzled.
>
> I have this object that uses a thread. The thread is encapsulated by the
> object, the object has Start and Stop methods to enable the client to
start
> or stop the thread.
>
> I found that the object will not be garbage collected while the thread is
> running. Fair enough, the documented explanation is that the GC compresses
> objects on the heap and needs to update references, the references will be
> invalid for a couple of moments which could be a problem if any thread is
> still using them while the GC is at work. So I have to stop my object
> explicitely before the application shuts down. In fact, if I don't, the
> application will not shutdown at all, the CLR will probably be waiting for
> me to stop the thread so it can do its final cleanup. Like I said, fair
> enough.
>
> But hey... This means that any applicaon that has some background thread
> running (which is not uncommon) will _never_ be subject to garbage
> collecting while it is running. This can't be right. It is a very common
> design pattern to have a modest background thread running that
periodically
> does some useful things and then goes to sleep for a couple of
milliseconds.
> Does this prevent the GC to kick in at all on the application's resources?
> It seems so, the finalizer of my object does not kick in while the thread
is
> running.
>
>
> What is true here and how do I go about it? It would help if there were a
> way for the thread to say "Hey, GC, I will enter a safe state now just to
> allow you to do your stuff. When you're done, wake me up again, okay?" But
I
> haven't found a way to do that (bluntly calling GC.Collect() from the
thread
> does not make any difference). So I am probably missing something. What is
> happening? Is there really no garbage collection for applications that do
> not take down all their threads on a regular basis?
>
> Martin.
>
>



Relevant Pages

  • Re: Generic Delegate Types explained (example)
    ... Unless you have specifically stated that the generic type has to be a value type, it can always be a reference type. ... To change the value of a string you have to replace it with a new string instance, which you can not do unless you send the string by reference to the method. ... example of generic delegate types taken from p. 108 of the C# 3.0 ... static Util UtilStringChanger2AndMoreStaticVersion ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: multithreaded tcp/ip monitoring application
    ... Passing a copy of a reference type variable just passes the reference, and so mutations in the instance can still be seen by multiple threads. ... The string type is a reference type, but a string instance is immutable and the string class is thread-safe. ... the variable itself is mutable and that's why you need the synchronization. ... But, and this is very important, the "str" variable itself is not referenced by the invoked delegate. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Load an object reference onto the stack ???
    ... The IL I generated calls a passed-in delegate. ... have a method called "Invoke". ... Load the object reference onto the stack. ...
    (microsoft.public.dotnet.framework)
  • Re: RaiseEvent
    ... // Store the reference to the delegate. ... assign a default delegate to the event that points to empty code. ... Making OnClick virtual also allows the derived class ... > public event EventHandler Click; ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Garbage collector question
    ... This "Target" property is used by the delegate to hold a reference to the ... (call this object XYZ), the object XYZ will never be garaged collected ...
    (microsoft.public.dotnet.languages.csharp)