asynchronousctp

async CTP: I am doing something wrong, the GUI is blocked


I am making some probes with async CTP but I don't get a good result, because the GUI is blocked.

I have an WPF application with a button and a textBox for a log. Then I have this code:

private async void btnAsync01_Click(object sender, RoutedEventArgs e)
        {
            UpdateTxtLog("Enter in Button Async01: " + System.DateTime.Now);
            await metodo01Async();
            UpdateTxtLog("Exit button Async01: " + System.DateTime.Now);
        }

private async Task slowMethodAsync()
        {
            UpdateTxtLog("Enter in slowMethod: " + System.DateTime.Now);
            Thread.Sleep(5000);
            UpdateTxtLog("Exit slowMethod: " + System.DateTime.Now);
        }

If am not wrong, set a method with "sync" (click event in this case), it let the method use the await, to return the point to execution to the method which call the actual method, then the execution return to the GUI.

So in the GUI,I click the button, then in the click event await to the slowMethod, how I use await with the slowMethod the control should be returned to the GUI, and then the GUI should not be blocked. However, the GUI is blocked and the txtLog not show any information until slowMethod finish.

Is this because slowMethod is executed in the same thread than the GUI? If I am wrong, with async normally use the same thread than the method which call the await method, but I think that the reason of the async avoid this.

How can I simulate an slowMethod without thread.Sleep? Perhaps this is the problem, because in slowMethod I sleep the thread, and the thread of slowMethod is the same than the GUI.

This makes me think that is always recommended execute in other thread the code of the async methods? If this is correct, which is the sense to use async if also I need to use task for not blocking the main thread?

When to use async and when to use tasks?

For this probes, I am following the examples in this web: http://www.codeproject.com/Articles/127291/C-5-0-vNext-New-Asynchronous-Pattern

In this example, it's used client.DownloadStringTaskAsync as slowMethod, but in my case, instead of using a WebClient, I use a dummy method, with a sleep to simulate a slowMethod. I think that is the unique difference.

Thanks. Daimroc.


Solution

  • Simulate waits using await TaskEx.Delay(5000), which executes an asynchronous sleep/delay.

    You may also want to read up some more on async/await. There are several good Channel9 videos; Stephen Toub, Eric Lippert, and many other Microsoft bloggers have excellent overviews. Jon Skeet's "eduasync" blog series is also good for really going deep. I've written up an async intro on my own blog, as have many others.

    Here's how async and await really work, in a nutshell:

    So in your case, btnAsync01_Click and slowMethodAsync both run on the UI thread. slowMethodAsync will run synchronously (executing Thread.Sleep), and then return to btnAsync01_Click, which awaits the already-completed task. Since the task is already completed, btnAsync01_Click just continues executing without yielding to the UI message loop.

    If you replace Thread.Sleep with await TaskEx.Delay, then btnAsync01_Click will start running on the UI thread, and will call slowMethodAsync (also running on the UI thread). When slowMethodAsync awaits the delay (which is not completed), it will return an incomplete task to btnAsync01_Click. btnAsync01_Click will await that task (which is not completed), and will return to the UI loop.

    When the delay expires, it will complete, and slowMethodAsync will resume (on the UI thread). When slowMethodAsync completes, its returned task will complete, and btnAsync01_Click will resume (on the UI thread).