10

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

如果“遗留线程”完成,GUI 前端就不能再做任何有用的事情了,所以我需要关闭 WPF 应用程序。因此,在线程方法的最后,我调用Application.Current.Shutdown().

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

Application.Current.Shutdown();

并打电话

Application.Current.Dispatcher.BeginInvokeShutdown();
4

3 回答 3

10

我做了一些更多的测试,现在我想我知道它们之间的区别了:

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");
    }
}
于 2010-05-31T08:43:59.867 回答
1

Shutdown()
的 MSDN 页面 BeginInvokeShutdown( ) 的 MSDN 页面

看来这只是术语的碰撞。BeginInvokeShutdown关闭该调度程序,您的应用程序理论上可以在之后继续存在(尽管没有调度程序,它会非常有限)。Shutdown但是实际上退出了您的应用程序,这就是您想要的。

于 2010-05-28T13:17:32.137 回答
0

顺便说一句,Daniel - 我们的应用程序是以相同的方式构建的 - WPF 前端到一个单独运行的 Win32 COM (Delphi) 应用程序。讨论和比较我们的方法会很有趣。

但是为什么我偶然发现了你的问题,因为我们的应用程序曾经调用 Dispatcher.BeginInvokeShutdown,除了一些没有正确终止的情况外,它运行良好。当我终于拿到一台可重现的机器时,切换到 Application.Current.Shutdown() 解决了这个问题。我仍然不明白是什么问题。

于 2011-04-27T23:02:45.667 回答