将异步/等待与结果混合 [英] Mixing async/await with Result

查看:50
本文介绍了将异步/等待与结果混合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我以几句话开头这个问题:

Let me just preface this question with a few things:

  1. 我已经阅读了几个SO问题,要求您执行此操作(例如异步/等待-异步编程的最佳做法再次说你不应该这样做
  1. I've read several SO questions saying that you should not do this (such as How to safely mix sync and async code)
  2. I've read Async/Await - Best Practices in Asynchronous Programming again saying you shouldn't do this

因此,我确实知道这不是最佳做法,也不需要任何人告诉我.这更多是为什么要这样做"的问题.

So I do know that this is not a best practice, and don't need anyone telling me such. This is more of a "why does this work" question.

顺带一提,这是我的问题:

With that out of the way, here is my question:

我编写了一个小型的GUI应用程序,其中包含2个按钮和一个状态标签.其中一个按钮将在100%的时间内通过同步和异步来再现死锁问题.另一个按钮调用相同的异步方法,但它包装在一个Task中,该方法有效.我知道这不是一个好的编码习惯,但是我想了解为什么,它没有相同的死锁问题.这是代码:

I've written a small GUI application that has 2 buttons and a status label. One of the buttons will reproduce the deadlock issue with sync and async 100% of the time. The other button calls the same async method but it is wrapped in a Task, this one works. I know this is not a good coding practice, but I want to understand why it doesn't have the same deadlock issue. Here is the code:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private async Task<string> DelayAsync()
    {
        await Task.Delay(1000);
        return "Done";
    }

    private void buttonDeadlock_Click(object sender, EventArgs e)
    {
        labelStatus.Text = "Status: Running";

        // causes a deadlock because of mixing sync and async code
        var result = DelayAsync().Result;
        // never gets here
        labelStatus.Text = "Status: " + result;
    }

    private void buttonWorking_Click(object sender, EventArgs e)
    {
        labelStatus.Text = "Status: Running";
        string result = null;

        // still technically mixes sync and async, but works, why?
        result = Task.Run(async () =>
        {
            return await DelayAsync();
        }).Result;

        labelStatus.Text = "Status: " + result;
    }
}

推荐答案

它之所以有效,是因为buttonWorking_Click异步代码(DelayAsync以及传递给Task.Runasync lambda)没有当前的SynchronizationContext,而buttonDeadlock_Click异步代码(DelayAsync)可以.您可以通过在调试器中运行并观看SynchronizationContext.Current来观察差异.

It works because the buttonWorking_Click async code (DelayAsync as well as the async lambda passed to Task.Run) does not have a current SynchronizationContext, whereas the buttonDeadlock_Click async code (DelayAsync) does. You can observe the difference by running in the debugger and watching SynchronizationContext.Current.

我会在我的博客文章不要解释死锁情况背后的细节阻止异步代码.

这篇关于将异步/等待与结果混合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆