Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 行为异步等待控制台应用程序与WPF_C#_Wpf_Asynchronous_Async Await_Deadlock - Fatal编程技术网

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

C# 行为异步等待控制台应用程序与WPF,c#,wpf,asynchronous,async-await,deadlock,C#,Wpf,Asynchronous,Async Await,Deadlock,我对async Wait很陌生。我想我理解了控制台应用程序的示例。当将相同的代码传输到WPF时,会出现死锁,我不知道确切原因 // All as expected // Output: // LongOperationAsync Start // Before task.Wait(); // LongOperationAsync End // After task.Wait(); // Result: 4711 class Program { public static void Ma

我对async Wait很陌生。我想我理解了控制台应用程序的示例。当将相同的代码传输到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();
}
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);
}
等效的WPF代码为:

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

    int result = await LongOperationAsync();

    Console.WriteLine("After LongOperationAsync");
    Console.WriteLine("Result: {0}", result);
    Console.ReadKey();
}
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是允许使用wait关键字的语法糖。wait异步地等待已经异步的操作,比如Task。延迟完成,而不阻塞原始线程。异步操作完成后,wait将在原始同步上下文中恢复执行。在WPF应用程序中,这就是UI线程。这就是允许在等待后更新UI的原因


async void仅适用于事件处理程序,如button2\u click。在所有其他情况下,应使用异步任务。异步void方法不能等待,应用程序无法知道它们是否完成

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

正确的控制台代码应为:

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

    int result = await LongOperationAsync();

    Console.WriteLine("After LongOperationAsync");
    Console.WriteLine("Result: {0}", result);
    Console.ReadKey();
}
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);
}
等效的WPF代码为:

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

    int result = await LongOperationAsync();

    Console.WriteLine("After LongOperationAsync");
    Console.WriteLine("Result: {0}", result);
    Console.ReadKey();
}
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是允许使用wait关键字的语法糖。wait异步地等待已经异步的操作,比如Task。延迟完成,而不阻塞原始线程。异步操作完成后,wait将在原始同步上下文中恢复执行。在WPF应用程序中,这就是UI线程。这就是允许在等待后更新UI的原因


async void仅适用于事件处理程序,如button2\u click。在所有其他情况下,应使用异步任务。异步void方法不能等待,应用程序无法知道它们是否完成

在您的示例中,您可以将按钮单击修改为异步。您的任务被阻塞,因为您从未启动过他,您无法在未启动任务的情况下通过等待呼叫

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

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

在您的示例中,您可以将按钮单击修改为异步。您的任务被阻塞,因为您从未启动过他,您无法在未启动任务的情况下通过等待呼叫

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

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

这两种情况下的代码都会阻塞。这两个例子在异步世界中都很糟糕,您永远不应该执行任何task.Wait或task.Result的操作。这方面的信息太多,无法回答。这是一个广泛的话题,我所能建议的就是继续做更多的研究。阅读同步上下文,阅读死锁,查找斯蒂芬·克利里(stephen cleary)的博客,利用谷歌,你会到达目的地。我认为你可以阅读这篇文章。尽管建议多读一些是公平的建议,但我认为我们可以做得更好。Panagiotis发布的代码几乎与我要发布的代码一模一样,我认为显示正确的代码非常有用。这两种情况下的代码都会阻塞。这两个例子在异步世界中都很糟糕,您永远不应该执行任何task.Wait或task.Result的操作。这方面的信息太多,无法回答。这是一个广泛的话题,我所能建议的就是继续做更多的研究。阅读同步上下文,阅读死锁,查找斯蒂芬·克利里(stephen cleary)的博客,利用谷歌,你会到达目的地。我认为你可以阅读这篇文章。尽管建议多读一些是公平的建议,但我认为我们可以做得更好。Panagiotis发布的代码几乎与我要发布的代码完全相同,我认为显示正确的代码非常有用。您可以等待任务的完成。var结果=等待长时间操作同步@安迪,我知道。但我必须从代码开始。OP在这一点上确实对更基本的问题感到困惑。我认为最好强调任务不是某种类或对象。你可以等待任务。var结果=等待长时间操作同步@安迪,我知道。但我必须从代码开始。OP在这一点上确实对更基本的问题感到困惑。我认为最好强调任务不是某种类或对象,任务已经开始了。实际的异步任务是由task.Delay生成的。等待不启动任何东西,它等待已经执行的任务任务任务已经启动。实际的异步任务是由task.Delay生成的。等待不启动任何东西,它等待已经执行的任务