Application.Current.Shutdown()与Application.Current.Dispatcher.BeginInvokeShutdown()

Dan*_*ose 8 c# wpf multithreading shutdown dispatcher

首先介绍一下:我有一个WPF应用程序,它是传统Win32应用程序的GUI前端.遗留应用程序在单独的线程中作为DLL运行.用户在UI中选择的命令在该"遗留线程"上调用.

如果"遗留线程"结束,GUI前端不能再做任何有用的事情了,所以我需要关闭WPF应用程序.因此,在线程的方法结束时,我打电话Application.Current.Shutdown().

由于我不在主线程上,我需要调用此命令.但是,我注意到Dispatcher也必须BeginInvokeShutdown()关闭调度程序.所以我的问题是:调用之间有什么区别

Application.Current.Shutdown();
Run Code Online (Sandbox Code Playgroud)

并打电话

Application.Current.Dispatcher.BeginInvokeShutdown();
Run Code Online (Sandbox Code Playgroud)

Dan*_*ose 9

我做了一些测试,现在我想我知道了差异:

1)如MSDN页面所述,BeginInvokeShutdown除了关闭Dispatcher之外,还清除/中止其队列.Shutdown首先处理Dispatcher队列中的所有项目.

关闭过程开始后,队列中的所有待处理工作项都将中止.

2)在应用程序中,我可以处理Application.Exit事件.当我调用Shutdown时会触发此事件,但在调用BeginInvokeShutdown时不会触发!这同样适用于Window.ClosingWindow.Closed.

至于相似之处,在两种情况下都退出主线程.根据其他正在运行的线程,这也会关闭进程:非进程线程在进程退出之前运行完成.

下面是我的测试代码.在Application_Startup中注释一个或另一个方法调用:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)