Application.Current.Shutdown () против Application.Current.Dispatcher.BeginInvokeShutdown () - PullRequest
7 голосов
/ 28 мая 2010

Сначала немного предыстории: у меня есть приложение WPF, которое является GUI-интерфейсом к устаревшему Win32-приложению. Устаревшее приложение работает как DLL в отдельном потоке. Команды, которые пользователь выбирает в пользовательском интерфейсе, вызываются в этом «устаревшем потоке».

Если «устаревшая нить» заканчивается, интерфейс GUI больше не может делать ничего полезного, поэтому мне нужно закрыть приложение WPF. Поэтому в конце метода потока я вызываю Application.Current.Shutdown().

Поскольку я не в основном потоке, мне нужно вызвать эту команду. Однако затем я заметил, что Диспетчер также имеет BeginInvokeShutdown() для выключения диспетчера. Итак, мой вопрос: в чем разница между вызовом

Application.Current.Shutdown();

и звонит

Application.Current.Dispatcher.BeginInvokeShutdown();

Ответы [ 3 ]

8 голосов
/ 31 мая 2010

Я провел еще несколько тестов, и теперь я думаю, что знаю различия:

1) Как указано на странице MSDN, BeginInvokeShutdown, помимо выключения Диспетчера, также очищает / прерывает свою очередь. Shutdown сначала обрабатывает все элементы в очереди Dispatcher.

Как только начинается процесс завершения работы, все ожидающие рабочие элементы в очереди отменяются.

2) В приложении я могу обработать событие Application.Exit . Это событие вызывается, когда я вызываю Shutdown, но НЕ запускается, когда я вызываю BeginInvokeShutdown! То же самое относится к Window.Closing и Window.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");
    }
}
1 голос
/ 28 мая 2010

Страница MSDN для выключения ()
Страница MSDN для BeginInvokeShutdown ()

Кажется, что это всего лишь столкновение терминологии. BeginInvokeShutdown закрывает этот диспетчер , ваше приложение теоретически может продолжать жить после этого (хотя без диспетчера оно будет довольно ограничено). Shutdown однако фактически выходит из вашего приложения, что вам и нужно.

0 голосов
/ 28 апреля 2011

Кстати, Даниэль - наше приложение построено таким же образом - интерфейс WPF к приложению Win32 COM (Delphi), работающему отдельно. Было бы интересно поговорить и сравнить наши подходы.

Но почему я наткнулся на ваш вопрос, так это то, что наше приложение вызывало Dispatcher.BeginInvokeShutdown, которое работало нормально, за исключением нескольких случаев, когда оно не завершалось должным образом. Когда я наконец заполучил машину, на которой это можно было воспроизвести, переключение на Application.Current.Shutdown () устранило проблему. Я до сих пор не понимаю, в чем была проблема.

...