Do I need to protect Thread
objects from the Garbage Collector? What about the object that contains the function that the thread runs?
Consider this simple server:
class Server{
readonly TcpClient client;
public Server(TcpClient client){this.client = client;}
public void Serve(){
var stream = client.GetStream();
var writer = new StreamWriter(stream);
var reader = new StreamReader(stream);
writer.AutoFlush = true;
writer.WriteLine("Hello");
while(true){
var input = reader.ReadLine();
if(input.Trim() == "Goodbye")
break;
writer.WriteLine(input.ToUpper());
}
client.Close();
}
}
static void Main(string[] args){
var listener = new TcpListener(IPAddress.Any, int.Parse(args[0]));
listener.Start();
while(true){
var client = listener.AcceptTcpClient();
var server = new Server(client);
var thread = new Thread(server.Serve);
thread.Start();
}
}
Should I wrap my thread objects in some sort of static collection to keep them from being swept up by the garbage collector?
Presumably, if the Thread
object itself stays alive, then the Server
object will live, because the thread holds a reference to the delegate which holds a reference to the target object. Or maybe the thread object itself is collected, but the actual thread continues to run. Now the Server
object is up for collection. And then what happens if it tries to access its field(s)?
Garbage collection makes my head spin some times. I'm glad I usually don't have to think about it.
Given the potential gotchas here, I would like to believe that the garbage collector is smart enough not to collect thread objects when the thread itself is still executing, but I can't find any documentation saying so. Reflector is of little help here, since much of the Thread
class is, unsurprisingly, implemented in MethodImplOptions.InternalCall
functions. And I'd rather not dig through my old outdated copy of SSCLI for answers (both because it's a pain, and because it's not a sure answer).
It is quite simple. The real execution thread is not Thread object. The program is executing in real Windows threads which stay alive regardless of what your .NET garbage collector does with your Thread objects. So it is safe for you; you don't need to care about Thread objects if you just want the program to keep running.
Also note that your threads don't get collected when they run, because they in fact belong to the application "roots". (Roots - it's how garbage collector knows what is alive.)
More details: A managed Thread object is accessible via Thread.CurrentThread
- that is something like a global static variable and those don't get collected. As I wrote earlier: Any managed thread which was started and now executing any code (even outside of .NET), doesn't lose its Thread object, because it is firmly connected to "roots".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With