在同步方法中执行异步方法的困惑[重复]

Posted

技术标签:

【中文标题】在同步方法中执行异步方法的困惑[重复]【英文标题】:Confusion on Execution of Asynchronous method inside the Synchronous method [duplicate] 【发布时间】:2021-09-25 23:10:31 【问题描述】:

这可能在某处得到解答,但想了解此场景的详细执行情况。今天,我遇到了调用异步方法的 MVC 动作(同步)方法。我不希望此执行同步或异步等待。所以,我没有使用 await 关键字或 wait 方法。但结果让我很惊讶。异步方法被执行了一些部分,一些只是跳过了执行。我已经重现了相同的场景,并且行为也相同。现在,我得到了执行,但想了解为什么这个异步和方法在同步方法中随机执行。我已经粘贴了代码 sn -p 并输出了这段代码。

    internal async Task<int> Method1Async()
    
        //await Task.Delay(1000);
        Console.WriteLine("Inside Method 1 : Before Calling await");
        await Task.FromResult(5);
        //await Task.Delay(1000);
        Console.WriteLine("Inside Method 1 : After Calling await");
        return await Task.FromResult(1);
    

    internal async Task<int> Method2Async()
    
        //await Task.Delay(1000);
        Console.WriteLine("Inside Method 2 : Before Calling await");
        var res = await Method1Async();
        await Task.Delay(1000);
        Console.WriteLine("Inside Method 2 : After Calling await");
        return res;
    

    internal async Task<int> Method3Async()
    
        //await Task.Delay(1000);
        Console.WriteLine("Inside Method 3 : Before Calling await");
        var res = await Method2Async();
        await Task.Delay(1000);
        Console.WriteLine("Inside Method 3 : After Calling await");
        return res;
    

    internal void Method4()
    
        Method3Async();
    

    public static void Main()
    
        Console.WriteLine("Inside Main : Before calling Method4");
        var demo =  new Demo();
        demo.Method4();
        Console.WriteLine("Inside Main : After calling Method4");
    

【问题讨论】:

@mjwills Console.Writeline 方法 2 和 3 的语句未执行。 我觉得 CLR 应该负责执行这些剩余的代码部分。 您已到达Main 方法的末尾。程序关闭 - 它停止运行。您希望等待异步代码执行,但还希望控制台被写入。你不能两者兼得。选择一个。 如果你错过了,我只在网络应用程序中遇到了这个,然后尝试在控制台应用程序中重现它。 我已经检查了这个答案,这一切看起来都像控制台应用程序,感觉很合理,但是对于网络应用程序呢? 【参考方案1】:

我不希望此执行同步或异步等待。所以,我没有使用 await 关键字或等待方法。

如您所见,ASP.NET 上的“一劳永逸”是危险的。

从技术上讲,“一劳永逸”的意思是“忘记”。如果您在没有同步或异步等待的情况下启动任务,那么您的代码明确表示它不关心该任务何时完成、如何完成或是否完成。

异步方法被执行了一些部分,一些只是跳过了执行......现在,我得到了执行但想了解为什么这个异步和方法在同步方法中随机执行。

最重要的是,关闭是正常的。如果您向 HTTP 请求发送响应,那么据 ASP.NET 所知,该请求已被处理;如果没有其他请求,则可以安全关闭。即发即弃的代码是请求外在的(在 HTTP 请求的范围之外),因此 ASP.NET 甚至不知道该代码的存在。

我觉得 CLR 应该负责执行剩下的部分代码。

不。 CLR 不能这样做,因为这会阻止一些关于 Task.WhenAny 的用例。

如果您需要提前返回,proper solution 是:

    为您的架构添加一个持久队列。例如,Azure 队列。 为您的架构添加一个单独的后台处理器。例如,Azure 函数。

然后,当您的 ASP.NET 应用程序想要提前返回时,它应该将需要执行的工作序列化为一条消息并将其写入持久队列,然后然后返回。单独的后台处理器应该从队列中读取消息并执行实际工作。

【讨论】:

我同意您的解释并感谢您的澄清。不知何故仍然不相信警告信息。我觉得它应该已经更新了。 I feel it should have been updated 你会如何更新它?它专门告诉您问题以及如何避免它。

以上是关于在同步方法中执行异步方法的困惑[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Async/Await 同步方法中的异步和异步方法中的异步

同步调用,异步回调和 Future 模式

Java 多线程 同步和异步

同步方法和异步方法的区别

为啥异步控制器方法像同步方法一样执行?

关于事件Event的说明