繁体   English   中英

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

[英]Behavior async await console application vs. WPF

我是异步等待的新手。 我想我了解控制台应用程序的示例。 将相同的代码传输到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;
}

两种情况下的代码块。 这两个例子都是不好的。 两者都不异步执行。

正确的控制台代码为:

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方法,应用程序也不知道它们是否完成。

在您的示例中,您可以将按钮单击修改为异步。 您的任务被阻止,因为您从不启动他,如果不启动任务,您将永远无法通过“ wait()”调用。

在修改后的按钮单击方法下面。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM