WPF 4.5: How to create child thread and continue task to UI main thread?

455 views Asked by At

I use WPF 4.5 and MVVM Caliburn Micro and have following WPF code:

public class MainViewModel: Screen
{
    public MainViewModel()
    {
        if (!ConnectServer())
        {
            Console.WriteLine("Connection failed");
            return;
        }
        // Following method can only be run if server connection established
        ProcessThis();
    }
}

My code above has only one chance to connect and if it is failed it shows the view and do nothing. If I use while(!ConnectServer()) it will block the UI thread all the time, means nothing will be displayed to user while the connection is still failed.It is very ugly.

What I want:

  1. if the connection is failed, means ConnectServer() returns false, it should wait for 10 seconds and try to connect again and again (eg. call a method RetryConnect()) till it is successful WITHOUT blocking the UI thread.
  2. And after it is connected, it should continue to main thread and run ProcessThis().

Theoretically I know it needs background separated thread, but I don't know how to implement it simple and good. Please feel free to use my sample code to explain. Thank you in advance.

1

There are 1 answers

0
Viacheslav Smityukh On BEST ANSWER

To start a background task you can use Task.Run method. And to execute a code in the main thread you can use Dispatcher of the page (in case of VM context I have placed call of Application.Current.Dispatcher)

public class MainViewModel: Screen
{
    public MainViewModel()
    {
        Task.Run(() =>
        {
            while (!ConnectServer())
            {
                Console.WriteLine("Connection failed");
                Thread.Sleep(10*1000);
            }

            // Following method can only be run if server connection established
            Application.Current.Dispatcher.Invoke(ProcessThis);
        }
    }
}

Instead of usage of Dispatcher you can utilize a new async/await functionality to implement it.

public class MainViewModel: Screen
{
    public MainViewModel()
    {
        Initialize();
    }
}

private async void Initialize()
{
        await Task.Run(async () =>
        {
            while (!ConnectServer())
            {
                Console.WriteLine("Connection failed");
                await Task.Delay(10*1000);
            }
        }

        // Following method can only be run if server connection established
        ProcessThis();
}