Search code examples
c#multithreading.net-corewindows-servicesnservicebus

.NET Threads and Garbage Collection/Phantom process


I'm currently trying to work out how best to run a .NET Core 2.x application as a Windows Service, specifically to run an NServiceBus endpoint for a messaging system. My original prototype was built from some of the Windows Service hosting docs from Particular. I then took that functioning prototype and turned it into a .NET Standard library for other team members to build from, but found that it wasn't super intuitive for them (or myself if I looked away from it for 2 weeks).

Naturally, after I built a functioning prototype and it was deployed to production, I found a more elegant solution that uses .NET Core's GenericHostBuilder, courtesy of a Mr. Steve Gordon. The majority of the code makes sense to me, but I'm hung up on the new Thread(...).Start();, likely because I don't have any specific experience with using Thread in C# and .NET.

  1. newing up a Thread and maintaining no reference to it feels really wrong. I'm concerned that doing that might lead to a memory leak or the Garbage Collector will pick it up? I did find this SO answer which gives me some reassurance that even if I don't hold a reference to the Thread, the CLR will. So it sounds like there shouldn't be any concern of the GC finalizing the thread, right?
  2. Could anyone explain to me why Abort() is not called for the Thread? Is it because the CLR manages threads and knows to stop other threads when the main thread shuts down? Or is does it have something to do with calling the ServiceBase.Stop() method in the IHostLifetime.StopAsync() method?

If these things can be explained in some documentation of Thread somewhere, I'm more than happy to get an "RTFM" and find the docs. I just haven't found anything that's given me a clear explanation at this point.


Solution

  • When a threads execution has finished and falls out of scope the, garbage collector will eventually reclaim the resources (when if feels the need). Thread also doesn't implement IDisposable so you really don't need to bother yourself with it hanging around (unless you are executing endless loops within it)

    In regards to Thread.Abort vs Thread.Interrupt, My honest answer is that you should never use either of these methods to terminate a thread. It is advisable not to use Thread.Abort or Thread.Interrupt methods at all - you should rather take advantage of synchronization objects (like, WaitHandles or Semaphores, etc, etc, etc) and perform a graceful termination of the threads you are using.

    In the wise words of Eric Lippert (the resident CLR wizard)

    In short, Thread.Abort is at best indicative of bad design, possibly unreliable, and extremely dangerous. It should be avoided at all costs; the only time you should ever even consider aborting a thread is in some sort of "emergency shutdown" code where you are attempting to tear down an appdomain as cleanly as possible.

    Some additional reading