10

最初に少し背景を説明します。従来のWin32アプリケーションのGUIフロントエンドであるWPFアプリケーションがあります。レガシーアプリは、別のスレッドでDLLとして実行されます。ユーザーがUIで選択したコマンドは、その「レガシースレッド」で呼び出されます。

「レガシースレッド」が終了すると、GUIフロントエンドは何も役に立たなくなるため、WPFアプリケーションをシャットダウンする必要があります。したがって、スレッドのメソッドの最後で、を呼び出しますApplication.Current.Shutdown()

私はメインスレッドにいないので、このコマンドを呼び出す必要があります。ただし、ディスパッチャもディスパッチャBeginInvokeShutdown()をシャットダウンする必要があることに気付きました。だから私の質問は:呼び出すことの違いは何ですか

Application.Current.Shutdown();

と呼び出し

Application.Current.Dispatcher.BeginInvokeShutdown();
4

3 に答える 3

10

私はさらにいくつかのテストを行いました、そして今私は違いを知っていると思います:

1)MSDNページに記載されているようにBeginInvokeShutdown、ディスパッチャをシャットダウンするだけでなく、キューをクリア/中止します。Shutdown最初に、ディスパッチャキュー内のすべてのアイテムを処理します。

シャットダウンプロセスが開始されると、キュー内の保留中のすべての作業項目が中止されます。

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-私たちのアプリケーションは同じ方法で構築されています-別々に実行されているWin32 COM(Delphi)アプリケーションへのWPFフロントエンド。私たちのアプローチについて話し、比較することは興味深いでしょう。

しかし、私があなたの質問に出くわした理由は、アプリケーションがDispatcher.BeginInvokeShutdownを呼び出していたためです。これは、正しく終了しなかったいくつかのケースを除いて、正常に機能しました。これが再現可能なマシンをついに手にしたとき、Application.Current.Shutdown()に切り替えると問題が修正されました。何が問題だったのかまだわかりません。

于 2011-04-27T23:02:45.667 に答える