C# Application.Current.Shutdown()与Application.Current.Dispatcher.BeginInvokeShutdown()的比较
首先介绍一下背景:我有一个WPF应用程序,它是一个遗留Win32应用程序的GUI前端。旧版应用程序作为DLL在单独的线程中运行。用户在UI中选择的命令将在该“旧线程”上调用 如果“遗留线程”完成,GUI前端将无法再做任何有用的事情,因此我需要关闭WPF应用程序。因此,在线程方法的末尾,我调用C# Application.Current.Shutdown()与Application.Current.Dispatcher.BeginInvokeShutdown()的比较,c#,wpf,multithreading,shutdown,dispatcher,C#,Wpf,Multithreading,Shutdown,Dispatcher,首先介绍一下背景:我有一个WPF应用程序,它是一个遗留Win32应用程序的GUI前端。旧版应用程序作为DLL在单独的线程中运行。用户在UI中选择的命令将在该“旧线程”上调用 如果“遗留线程”完成,GUI前端将无法再做任何有用的事情,因此我需要关闭WPF应用程序。因此,在线程方法的末尾,我调用Application.Current.Shutdown() 由于我不在主线程上,因此需要调用此命令。但是,随后我注意到,Dispatcher还具有BeginInvokeShutdown()来关闭Dispat
Application.Current.Shutdown()
由于我不在主线程上,因此需要调用此命令。但是,随后我注意到,Dispatcher还具有BeginInvokeShutdown()
来关闭Dispatcher。所以我的问题是:调用
Application.Current.Shutdown();
和呼唤
Application.Current.Dispatcher.BeginInvokeShutdown();
这似乎只是术语上的冲突
BeginInvokeShutdown
关闭该调度器,理论上,您的应用程序可以在之后继续运行(尽管没有调度器,它将非常有限)<代码>关闭但实际上退出了应用程序,这正是您所需要的。我做了更多的测试,现在我想我知道了区别:
1) 如MSDN页面中所述,BeginInvokeShutdown
,除了关闭调度程序外,还清除/中止其队列<代码>关机首先处理调度程序队列中的所有项目
一旦关闭过程开始,队列中所有挂起的工作项都将中止
2) 在应用程序中,我可以处理事件。此事件在我调用Shutdown时触发,但在我调用BeginInvokeShutdown时未触发!这同样适用于和
至于相似之处,在这两种情况下,主线程都退出。根据其他正在运行的线程,这也会关闭进程:在进程退出之前,非后台线程将一直运行到完成
下面是我的测试代码。在应用程序启动时注释一个或另一个方法调用:
public partial class App
{
private void Application_Exit(object sender, ExitEventArgs e)
{
MessageBox.Show("Exiting");
}
private void Application_Startup(object sender, StartupEventArgs e)
{
var testThread = new Thread(
() =>
{
Thread.Sleep(2000);
Application.Current.Dispatcher.BeginInvokeShutdown(System.Windows.Threading.DispatcherPriority.Send);
//Application.Current.Dispatcher.BeginInvoke(new Action(() => Application.Current.Shutdown()));
});
testThread.Start();
}
}
public partial class Window1
{
public Window1()
{
this.InitializeComponent();
Dispatcher.BeginInvoke(new Action(() =>
{
Thread.Sleep(1000);
Console.WriteLine("One");
}));
Dispatcher.BeginInvoke(new Action(() =>
{
Thread.Sleep(1000);
Console.WriteLine("Two");
}));
Dispatcher.BeginInvoke(new Action(() =>
{
Thread.Sleep(1000);
Console.WriteLine("Three");
}));
Dispatcher.BeginInvoke(new Action(() =>
{
Thread.Sleep(1000);
Console.WriteLine("Four");
}));
}
private void Window_Closed(object sender, EventArgs e)
{
Console.WriteLine("Closed");
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Console.WriteLine("Closing");
}
}
顺便说一句,Daniel—我们的应用程序也是以同样的方式构建的—WPF前端是一个单独运行的Win32 COM(Delphi)应用程序。讨论和比较我们的方法会很有趣
但我偶然发现您的问题的原因是,我们的应用程序曾经调用Dispatcher.BeginInvokeShutdown,它工作正常,只有少数情况下没有正确终止。当我最终在一台机器上得到了这一点是可以复制的,切换到Application.Current.Shutdown()解决了这个问题。我仍然不明白问题出在哪里。这正是文档中没有回答的问题:关闭应用程序的dispatcher是否也会关闭应用程序?我为此构建了一个简单的WPF测试应用程序。为了模拟您的代码,我做了:
threadt=newthread(newthreadstart(delegate(){Thread.Sleep(50000);}));t、 Start();Application.Current.Dispatcher.BeginInvokeShutdown(System.Windows.Threading.DispatcherPriority.Normal)代码>。Dispatcher shutdown杀死了它的所有者线程并关闭了窗口,但没有杀死后台线程。两个小区别:1)我在第二个线程中调用shutdown(尽管通过测试我可以看到它没有任何区别)。2) 我将第二个线程设置为背景线程(IsBackground=true)。这样,如果主线程退出,它也会被杀死。我猜这是因为调用Dispatcher.BeginInvokeShutdown()会中止/清除任何挂起的消息。在我的例子中,我还对Window.Closing/Closed cases和Application.Exit(关闭Win32部件)进行了大量清理。