Как закрыть окно WPF внутри задачи - PullRequest
1 голос
/ 09 апреля 2019

Мне нужно запустить задачу для проверки соединения.

Мои окна не должны быть заморожены во время этой проверки.

Поэтому я запускаю задачу и закрываю окно в концеэта задача.

Но это возвращает исключение: InvalidOperationException: 'Вызывающий поток не может получить доступ к этому объекту, потому что другой поток владеет им'.

Например:

        private void Window_ContentRendered(object sender, System.EventArgs e)
        {
            Task.Run(() =>
            {
                ConnectionState = false;

                if (NetworkTools.CheckGlobalConnection() == (ConnectionStatus.NetworkConnectionSuccess, ConnectionStatus.ServerConnectionSuccess))
                {
                    ConnectionState = true;
                }

                this.Close();
            });
        }

Как мне закрыть окно в конце задачи, не замораживая его и не имея этого исключения?(У меня есть индикатор выполнения, который вращается бесконечно)

Ответы [ 3 ]

6 голосов
/ 09 апреля 2019

Или вы можете просто использовать async await .Task.Run разгрузится, и ожидающий создаст продолжение текущего SynchronizationContext.В свою очередь, возвращение управления к UI и закрытие на правой нити.

private async void Window_ContentRendered(object sender, System.EventArgs e)
{
   await Task.Run(() =>
         {
            ConnectionState = false;

            if (NetworkTools.CheckGlobalConnection() == (ConnectionStatus.NetworkConnectionSuccess, ConnectionStatus.ServerConnectionSuccess))
               ConnectionState = true;
         });

   this.Close();
}

Также, как отмечалось, Calling ConfigureAwait(false), было бы неправильно делать вэтот случай

2 голосов
/ 09 апреля 2019

В качестве альтернативного метода вы можете использовать ContinueWith

private void Window_ContentRendered(object sender, System.EventArgs e)
    {
        Task.Run(() =>
         {
            // Your code

         }).ContinueWith((tsk) =>
         {
             this.Close();
         }, TaskScheduler.FromCurrentSynchronizationContext());
    }
2 голосов
/ 09 апреля 2019

Используйте Dispatcher, чтобы поставить в очередь логику закрытия окна в уникальном потоке пользовательского интерфейса. Что-то вроде Dispatcher.Invoke( () => { // close window here });

Все, что передается в .Invoke(...) в качестве делегата, вызывается в потоке пользовательского интерфейса и, следовательно, имеет право доступа ко всем элементам пользовательского интерфейса. Это распространенный (и единственный правильный) способ борьбы с мутациями пользовательского интерфейса в не-пользовательских потоках.

...