在以下WPF代码中,单击一次按钮后,将启动新的前台线程。然后我关闭了WPF窗口,我可以看到在Windows任务管理器中,该进程在Thread.Sleep(100000)
结束前不会被终止。我可以理解它,因为前台线程可以阻止进程终止,因为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);
}
}
但是当我在控制台程序中尝试几乎相同的事情时,该过程会在关闭控制台窗口后立即终止。有人可以帮忙解释这些差异吗?
class Program
{
static void Main(string[] args)
{
new Thread(Go).Start();
}
private static void Go()
{
Thread.Sleep(100000);
}
}
答案 0 :(得分:4)
但是当我在控制台程序中尝试几乎相同的事情时,该过程会在关闭控制台窗口后立即终止。有人可以帮忙解释这些差异吗?
<强> TL; DR; 区别在于它是一个控制台应用,您点击关闭框。这与从任务管理器中进行核对非常相似。此外,所有控制台应用程序主线程也是前台线程。请参阅本答案末尾的示例。
如果单击控制台应用程序上的关闭框,Windows将终止所有线程并关闭控制台应用程序,无论线程是后台还是前台。对于GUI应用程序,如WinForms或WPF; 的规则“一旦属于某个进程的所有前台线程都已终止,公共语言运行库将结束该进程”。与控制台应用程序不同,单击GUI应用程序上的关闭框和进程终止之间没有直接链接
如果在调试器中运行以下代码,它将等待另一个线程完成。但是,单击关闭框会使进程和控件返回到 Visual Studio ,从而证明该进程确实已退出并且未播放隐藏 - 像Windows Forms一样可以处理前台线程。 (关闭一个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);
}
}
}
假设您没有点击关闭框,那么控制台应用程序将不会终止,直到所有线程都完成。
MSDN:
一旦属于某个进程的所有前台线程都已终止,公共语言运行库就会结束该进程
您可以通过以下方式证明此控制台应用行为:
static void Main(string[] args)
{
var thread = Thread.CurrentThread;
Console.WriteLine("{0} thread {1} sleeping", thread.IsBackground ? "Background" : "Foreground", thread.ManagedThreadId);
Thread.Sleep(100000);
}
现在我们不会在这里产生任何新线程,但只需单击关闭框即可将该过程发送到遗忘状态。但是等等,您是否看到主线程实际上是前台线程?