Reputation: 11
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
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
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