But when I try almost the same thing in the console program, the process ends immediately after closing the console window. Can anyone help explain the differences?
TL DR; The difference is that this is a console application, and you click the close button. This is very similar to nuking from task manager. In addition, all the main threads of the console application are foreground threads . See the example at the end of this answer.
If you press the close button in a console application, Windows will kill all threads and turn off the console application regardless of whether the threads are background or front. For a graphical interface such as WinForms or WPF; rule "After all the threads of the foreground belonging to the process are completed, the common execution language is applied." Direct connection between pressing the button to close the GUI application and terminating the process, unlike console applications
If you run the following code in the debugger, it will wait for another thread to complete. However, clicking the close button closes the process, and control returns to Visual Studio, thus proving that the process has actually completed and is not working in search mode, such as Windows Forms. do with front threads. (closing the main window of the WinForms application with the foreground threads that are still running just closes the window, not necessarily the process)
namespace ConsoleApplication10 { class Program { static void Main(string[] args) { new Thread(Go).Start(); Console.WriteLine("Main thread {0} exiting", Environment.CurrentManagedThreadId); } private static void Go() { var thread = Thread.CurrentThread; Console.WriteLine("{0} thread {1} sleeping",thread.IsBackground ? "Background" : "Foreground", thread.ManagedThreadId); Thread.Sleep(100000); } } }
Assuming you donβt click on the close box, the console application will not terminate until all threads are complete.
MSDN:
Once all the foreground threads belonging to the process are complete, the common language runtime terminates the process
A simple way to prove things
You can prove this behavior in a console application simply by:
static void Main(string[] args) { var thread = Thread.CurrentThread; Console.WriteLine("{0} thread {1} sleeping", thread.IsBackground ? "Background" : "Foreground", thread.ManagedThreadId); Thread.Sleep(100000); }
Now we are not creating new threads, but just a simple click to close the window to send the process into oblivion. But wait, did you see that the main thread is actually the front thread ?