user3311100 user3311100 - 4 months ago 20
C# Question

UI still locked up even with multi threading

I'm working on a project and I've hit a lot of road blocks with the UI.
In this case create a new thread to update the UI so that the UI main thread is left open allowing you to still use the UI.

I'm not sure what the problem with this is. I think that maybe I'm using dispatcher to create thread that instead of creating a thread uses the main thread?? Its also worth noting that my

MainWindow
is singleton instance.

private void button_Click(object sender, RoutedEventArgs e)
{
if (go)
{
city = textBox.GetLineText(0);
if (city == "exit")
{
Environment.Exit(0);
}

Thread t1 = new Thread(new ThreadStart(
delegate
{
this.Dispatcher.Invoke(DispatcherPriority.Background, new Action(start));
}));
t1.Start();
//await Task.Run(() => start());
}
}

Answer

You don't need to create a new thread. When you're using async and await, a new thread will be automatically assigned from the thread pool. Just make your button_Click event handler async as mentioned in code below and call the long running task using await keyword.

private async void button_Click(object sender, RoutedEventArgs e)
{
    if (go)
    {
        city = textBox.GetLineText(0);
        if (city == "exit")
        {
            Environment.Exit(0);
        }

        await Task.Run(() => start());
    }
}

What will happen here is when you click on the button the event will be handled. If the condition is satisfied, the long running task is initiated in this line await Task.Run(() => start());. Then it will return to the UI thread without blocking it ie the UI will still be responsive while another thread is executing the long running process in background.

Please read Asynchronous Programming with async and await (C#) on MSDN.

EDIT : Since you want to control UI elements in your start() method, use the below approach :

private async void button_Click(object sender, RoutedEventArgs e)
{
    if (go)
    {
        city = textBox.GetLineText(0);
        if (city == "exit")
        {
            Environment.Exit(0);
        }

        await start();
    }
}

private async Task start()
{
    await Task.Run(async () => 
    {
       // long running task here
    });   

    // UI Control code here.
}