Sorry if my question seems naive. I’m new to C# and .Net, and still wrap my head around them.
I come from a Go-Lang background, and try to learn C#/.Net multithreading.
In Go the main thread will run and complete its logic regardless of other threads if no wait is used.
I thought it should be the same in C#, however, the code below allow all threads to run completely.
Which means Main thread waits other threads to complete, without using join() or any other wait techniques.
Could you please, let me know what I missed here or misunderstood.
namespace TestThread
{
internal class Program
{
static void Main(string[] args)
{
Thread T1 = new Thread(PrintY);
T1.Start();
// The following is the funtion of the Main thread.
for (int i = 0; i < 10; i++) Console.Write("x");
}
static void PrintY()
{
for (int i = 0; i < 100; i++)
{
Console.Write("Y");
Thread.Sleep(100);
}
}
}
}
The output is like the following:
xxxxxxxxxYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
I expected at most one Y in the results before the Main method finishes and therefore the process terminates. What is keeping the process alive when the main thread is completed?
>Solution :
When you are creating Thread via constructor by default it’s Thread.IsBackground is set to false:
A thread is either a background thread or a foreground thread. Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. Once all foreground threads belonging to a process have terminated, the common language runtime ends the process. Any remaining background threads are stopped and do not complete.
And:
By default, the following threads execute in the foreground (that is, their
IsBackgroundproperty returnsfalse):
- The primary thread (or main application thread).
- All threads created by calling a Thread class constructor.
So it will prevent the app from terminating. If you want your threads to allow the application to terminate you can set this property to false:
Thread T1 = new Thread(PrintY);
T1.IsBackground = true;
...
Also note that manually creating threads is rarely needed operation in modern C#. After introduction of Task Parallel Library (TPL) usually Task APIs are used instead of directly manipulating the threads (_ = Task.Run(PrintY); for example can be used in this case).