The startup parameter (which is server.Serve in your case) in the thread designer is a delegate that you already knew.
Presumably, if the Thread object itself remains alive, then the Server object will live, because the thread refers to the delegate which contains a reference to the target object
This is what C # in depth from Jon Skeet has to say about delegate’s goal life
It is worth knowing that a delegate instance will prevent garbage collection if the delegate instance itself cannot be collected.
So yes, server will not be built while var thread is in scope. If var thread goes out of scope before thread.start is called (and there are no other links), then yes, this can be compiled.
Now the big question. Thread.Start () is called and the thread goes out of scope until server.Serve completes, whether the GC can collect the thread.
Instead of digging, let's just test it
class Program { static void Main(string[] args) { test(); GC.Collect(2); GC.WaitForPendingFinalizers(); Console.WriteLine("test is over"); } static void test() { var thread = new Thread(() => { long i = 0; while (true) { i++; Console.WriteLine("test {0} {1} {2} ", Thread.CurrentThread.Name, Thread.CurrentThread.ManagedThreadId i); Thread.Sleep(1000);
This is the result. (after adding threadID)
test MyThread 3 1 test is over test MyThread 3 2 test MyThread 3 3 test MyThread 3 4 test MyThread 3 5
Therefore, I call a method that creates a thread and starts it. The method ends so that var thread out of scope. But even though I called GC, and the thread variable is out of scope, the thread continues to work.
So, as long as you start the thread before it goes out of scope, everything will work as expected
Update To clarify GC.Collect
It makes it immediately collect garbage of all generations.
Everything that can be collected will be. This is not so, as the comments say “a little more than an expression of intent”. (If he had no reason to caution against calling him). However, I added the argument "2" to make sure that it is gen0 through gen2.
Your assessment of the finalizers is worth noting. So I added GC.WaitForPendingFinalizers , which
... pauses the current thread until the thread that processes the finalizer queue empties the queue.
This means that all finalizers that need to be processed are indeed processed.
The sampling point was that as long as you start the thread, it will work until it is interrupted or terminated, and that the GC will not somehow interrupt the thread just because var thread exited scope
As a third-party, Al Kepp is correct, that indeed, as soon as you start the thread, System.Threading.Thread is rooted. You can find out by using the SOS extension.
eg.
!do 0113bf40 Name: System.Threading.Thread MethodTable: 79b9ffcc EEClass: 798d8ed8 Size: 48(0x30) bytes File: C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll Fields: MT Field Offset Type VT Attr Value Name 79b88a28 4000720 4 ....Contexts.Context 0 instance aaef947d00000000 m_Context 79b9b468 4000721 8 ....ExecutionContext 0 instance aaef947d00000000 m_ExecutionContext 79b9f9ac 4000722 c System.String 0 instance 0113bf00 m_Name 79b9fe80 4000723 10 System.Delegate 0 instance 0113bf84 m_Delegate 79ba63a4 4000724 14 ...ation.CultureInfo 0 instance aaef947d00000000 m_CurrentCulture 79ba63a4 4000725 18 ...ation.CultureInfo 0 instance aaef947d00000000 m_CurrentUICulture 79b9f5e8 4000726 1c System.Object 0 instance aaef947d00000000 m_ThreadStartArg 79b9aa2c 4000727 20 System.IntPtr 1 instance 001D9238 DONT_USE_InternalThread 79ba2978 4000728 24 System.Int32 1 instance 2 m_Priority 79ba2978 4000729 28 System.Int32 1 instance 3 m_ManagedThreadId 79b8b71c 400072a 18c ...LocalDataStoreMgr 0 shared static s_LocalDataStoreMgr >> Domain:Value 0017fd80:NotInit << 79b8e2d8 400072b c ...alDataStoreHolder 0 shared TLstatic s_LocalDataStore
This is a thread called MyThread.
!do -nofields 0113bf00 Name: System.String MethodTable: 79b9f9ac EEClass: 798d8bb0 Size: 30(0x1e) bytes File: C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll String: MyThread
Why yes, it is.
What is he attached to?
!GCRoot 0113bf40 Note: Roots found on stacks may be false positives. Run "!help gcroot" for more info. Scan Thread 7708 OSTHread 1e1c Scan Thread 4572 OSTHread 11dc Scan Thread 9876 OSTHread 2694 ESP:101f7ec:Root: 0113bf40(System.Threading.Thread) ESP:101f7f4:Root: 0113bf40(System.Threading.Thread) DOMAIN(0017FD80):HANDLE(Strong):9b11cc:Root: 0113bf40(System.Threading.Thread)
As "Production Debugging for .NET Framework Applications" says this is the root.
Note that! GCRoot was launched after its launch. Before it was launched, it did not have HANDLE (Strong).
If the output is HANDLE (Strong), a strong link has been found. This means that the object is rooted and garbage cannot be collected. Other reference types can be found in the Appendix.
For more information on how managed threads are mapped in OS threads (and how you can confirm this with SOS extensions), see this article by Yun Jin,