0

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?

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
helhadad
  • 21
  • 7

1 Answers1

2

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 IsBackground property returns false):

  • 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).

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • 1
    @helhadad I'm not familiar with go but I would say (as I wrote in the answer) - you should better look into using `Task`s rather then `Thread`s. – Guru Stron Jan 06 '22 at 23:37
  • I wonder if does it make sense of using join() in foreground threads. – helhadad Jan 06 '22 at 23:40
  • @helhadad it depends. If you want to suspend current method execution until the thread is finished - then yes. But again - usually it is better to use `Tasks` (and `async-await` for similar purpose). – Guru Stron Jan 06 '22 at 23:44