简体   繁体   English

前台线程不会阻止控制台进程终止吗?

[英]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. 在以下WPF代码中,单击按钮后,将启动新的前台线程。 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. 然后关闭WPF窗口,可以看到在Windows任务管理器中,直到Thread.Sleep(100000)结束,该过程才会终止。 I could understand it because foreground threads could prevent process from terminating as MSDN doc says. 我能理解它,因为如MSDN doc所述,前台线程可能会阻止进程终止。

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; TL; DR; 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. 如果单击控制台应用程序上的关闭框,则Windows将杀死所有线程并关闭控制台应用程序,而不管线程是后台线程还是前台线程。 For a GUI app such as WinForms or WPF; 对于GUI应用程序,例如WinForms或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 与控制台应用程序不同,在GUI应用程序上单击关闭框和进程终止之间没有直接链接。

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. 但是, 单击关闭框会使该过程无效,并且控件返回到 Visual Studio,从而证明该过程确实已经退出并且没有像Windows Forms可以使用前台线程那样进行捉迷藏。 (closing a WinForms main app window with foreground threads still running just closes the window, not necessarily the process) (关闭仍在运行中的前台线程的WinForms主应用程序窗口只会关闭该窗口,而不必关闭进程)

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: 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 ? 但是,等等,您是否看到主线程实际上是前台线程

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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