我是异步等待的新手。我想我了解控制台应用程序的示例。将相同的代码传输到WPF时,会出现死锁,我也不知道为什么。
// 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;
}
}
这是阻塞的WPF代码:
// 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;
}
答案 0 :(得分:5)
在两种情况下,代码均会阻塞。这两个例子都是不好的。两者都不异步执行。
正确的 控制台代码为:
public static async Task Main()
{
Console.WriteLine("Before LongOperationAsync");
int result = await LongOperationAsync();
Console.WriteLine("After LongOperationAsync");
Console.WriteLine("Result: {0}", result);
Console.ReadKey();
}
等效的WPF代码为:
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
是语法糖,它允许使用await
关键字。 await
异步唤醒,以完成已经Task.Delay()
之类的已经异步的操作,而不会阻塞原始线程。该异步操作完成后,await
将在原始同步上下文中恢复执行。在WPF应用程序的情况下,这就是UI线程。这就是允许在await
之后更新UI的原因。
async void
仅适用于事件处理程序,例如button2_click
。在所有其他情况下,应使用async Task
。无法等待async void
方法,应用程序也不知道它们是否完成。
答案 1 :(得分:-1)
在您的示例中,您可以将按钮单击修改为异步。您的任务受阻,因为您从不启动他,也无法在不启动任务的情况下传递“ wait()”调用。
在修改后的按钮单击方法下面。
private async void button2_Click(object sender, EventArgs e)
{
var result = await LongOperationAsync();
Debug.WriteLine("Result: {0}", result);
}