行为异步等待控制台应用程序与WPF

0 c# wpf deadlock asynchronous async-await

我是异步等待的新手.我想我理解了控制台应用程序的例子.将相同的代码传输到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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是阻止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;
}
Run Code Online (Sandbox Code Playgroud)

Pan*_*vos 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();
}
Run Code Online (Sandbox Code Playgroud)

等效的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);
}
Run Code Online (Sandbox Code Playgroud)

async是语法糖,允许使用await关键字.异步await 等待已经Task.Delay()完成的异步操作,而不阻塞原始线程.当异步操作完成时,await继续在原始同步上下文中执行.在WPF应用程序的情况下,这是UI线程.这是允许在更新后更新UI的内容await.

async void仅适用于事件处理程序,例如button2_click.在所有其他情况下async Task应该使用.async void方法无法等待,应用程序无法知道它们是否已完成.