Eros Guil
Eros Guil

Reputation: 31

How to close WPF window inside of a Task

I need to run a task to check the connection.

My windows should not be frozen during this check.

So I start the Task, and close my window at the end of this task.

But this returns an exception: InvalidOperationException:'The calling thread cannot access this object because another thread owns it'.

Like this :

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

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

                this.Close();
            });
        }

How do I close my window at the end of the task without freezing it and without having this exception ? (I have a progress bar that rotates indefinitely)

Upvotes: 1

Views: 1299

Answers (3)

Justin CI
Justin CI

Reputation: 2741

As an alternate method you can use ContinueWith

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

         }).ContinueWith((tsk) =>
         {
             this.Close();
         }, TaskScheduler.FromCurrentSynchronizationContext());
    }

Upvotes: 2

TheGeneral
TheGeneral

Reputation: 81493

Or you could just use async await. Task.Run will offload and the await will create a continuation on current SynchronizationContext. In turn giving control back to the UI and closing on the right thread.

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();
}

Also as noted, Calling ConfigureAwait(false), would not be the right thing to do in this case

Upvotes: 8

Zazaeil
Zazaeil

Reputation: 4109

Use Dispatcher to queue window closing logic on the unique UI thread. Something like Dispatcher.Invoke( () => { // close window here });

Whatever is passed into .Invoke(...) as a delegate, is invoked on the UI thread and hence has right to access all UI elements. It is common (and the only correct) way to deal with UI-mutations within non-UI threads.

Upvotes: 2

Related Questions