简体   繁体   中英

Foreground thread don't stop a console process from terminating?

In the following WPF code, once button is clicked, a new foreground thread is started. Then I close the WPF window, I could see that in Windows task manager, the process won't be terminated until Thread.Sleep(100000) ends. I could understand it because foreground threads could prevent process from terminating as MSDN doc says.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        new Thread(Go).Start();
    }

    private void Go(object obj)
    {
        Thread.Sleep(100000);
    }
}

But when I try almost the same thing in a console program, the process terminates immediately after I close the console window. Anybody could help to explain the differences?

class Program
{
    static void Main(string[] args)
    {
        new Thread(Go).Start();
    }

    private static void Go()
    {
        Thread.Sleep(100000);
    }
}

But when I try almost the same thing in a console program, the process terminates immediately after I close the console window. Anybody could help to explain the differences?


TL; DR; The difference is that it is a console app and you are clicking the close box . It's pretty similar to nuking it from Task Manager . Additionally, all console app primary threads are foreground threads too. See example at end of this answer.


If you click the close box on a console app, Windows will kill all thread and shutdown your console app regardless of whether the threads are background or foreground. For a GUI app such as WinForms or WPF; the rule of "Once all foreground threads belonging to a process have terminated, the common language runtime ends the process" applies. There is no direct link between clicking the close box on a GUI app and process termination, unlike console apps

If you run the following code in the debugger, it will wait for the other thread to complete. However, clicking the close box nukes the process and control returns to Visual Studio thus proving the process really did exit and isn't playing hide-and-seek like Windows Forms can do with foreground threads. (closing a WinForms main app window with foreground threads 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 then the console app won't terminate until all threads are finished.

MSDN:

Once all foreground threads belonging to a process have terminated, the common language runtime ends the process

An easy way to prove things

You can prove this console app behavior by simply:

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're not spawning any new threads here but a simple click of the close box is sufficient to send the process to oblivion. But wait, did you see that the main thread is in fact a foreground thread ?

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM