A5000
A5000

Reputation: 11

Behavior async await console application vs. WPF

I am quite new to async await. I think I understood the example of the console application. When transferring the identical code to the WPF, there is a deadlock and I do not know exactly why.

// All as expected
// Output:
// LongOperationAsync Start
// Before task.Wait();
// LongOperationAsync End
// After task.Wait();
// Result: 4711

class Program {
    public static void Main() {
        Task<int> task = LongOperationAsync();
        //Console.ReadKey();
        Console.WriteLine("Before task.Wait();");
        task.Wait();
        Console.WriteLine("After task.Wait();");
        var result = task.Result;
        Console.WriteLine("Result: {0}", result);
        Console.ReadKey();
    }

    static async Task<int> LongOperationAsync() {
        Console.WriteLine("LongOperationAsync Start");
        await Task.Delay(1000);
        Console.WriteLine("LongOperationAsync End");
        return 4711;
    }
}

and here is the blocking WPF code:

// WPF handler Output:
// LongOperationAsync Start
// Before task.Wait(); => Blocking

private void button2_Click(object sender, EventArgs e) {
    Task<int> task = LongOperationAsync();
    Debug.WriteLine("Before task.Wait();");
    task.Wait();
    Debug.WriteLine("After task.Wait();");
    var result = task.Result;
    Debug.WriteLine("Result: {0}", result);
}

private async Task<int> LongOperationAsync() {
    Debug.WriteLine("LongOperationAsync Start");
    await Task.Delay(1000);
    Debug.WriteLine("LongOperationAsync End");
    return 4711;
}

Upvotes: 1

Views: 331

Answers (2)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131512

The code blocks in both cases. Both examples are bad. Neither executes asynchronously.

The correct Console code would be :

public static async Task Main()
{
    Console.WriteLine("Before LongOperationAsync");

    int result = await LongOperationAsync();

    Console.WriteLine("After LongOperationAsync");
    Console.WriteLine("Result: {0}", result);
    Console.ReadKey();
}

The equivalent WPF code would be :

private async void button2_Click(object sender, EventArgs e)
{
    Debug.WriteLine("Before LongOperationAsync");

    int result = await LongOperationAsync();

    Debug.WriteLine("After LongOperationAsync");
    Debug.WriteLine("Result: {0}", result);
}

async is syntactic sugar that allows the use of the await keyword. await awaits asynchronously for an already asynchronous operation like Task.Delay() to complete, without blocking the original thread. When that asynchronous operation completes, await resumes execution in the original synchronization context. In the WPF application's case, that's the UI thread. That's what allows updating the UI after an await.

async void is only meant for event handlers, like button2_click. In all other cases async Task should be used. async void methods can't be awaited and the application can't know whether they completed or not.

Upvotes: 5

CGuy
CGuy

Reputation: 38

In your example you can modify your button-click to async. Your Task is blocking because you never start him, you can never pass the "wait()" call without starting the task.

Below the modified button click method.

private async void button2_Click(object sender, EventArgs e)
{
    var result = await LongOperationAsync();
    Debug.WriteLine("Result: {0}", result);
}

Upvotes: -1

Related Questions