c#异步方法不起作用[重复]

Posted

技术标签:

【中文标题】c#异步方法不起作用[重复]【英文标题】:c# asynchronous method not work [duplicate] 【发布时间】:2018-09-12 17:36:01 【问题描述】:

在使用 vs 2015 编写的控制台应用程序上考虑此代码:

using System;
using System.Threading.Tasks;

public class Example

    public static void Main()
    
        Console.WriteLine("Wait please....");
        DateTime time1 = DateTime.Now;
        Task task1 = MyAsyncFun1();
        Task task2 = MyAsyncFun2();
        task1.Wait();
        task2.Wait();
        DateTime time2 = DateTime.Now;
        Console.WriteLine("time elapsed: " + 
        (time2 -  time1).TotalSeconds);
        Console.ReadLine();
    
    private static async Task MyAsyncFun1()
    
        await Task.Yield();
        System.Threading.Thread.Sleep(2000);
    
    private static async Task MyAsyncFun2()
    
        await Task.Yield();
        System.Threading.Thread.Sleep(2000);
    

有两种异步调用的方法,一切正常,“经过的时间”不超过 2 秒,因为执行是并行的。

但是当我在这样的 ApiController 的 acion 方法中编写这段代码时:

public class MyController : ApiController

    private static async Task MyAsyncFun1()
    
        await Task.Yield();
        System.Threading.Thread.Sleep(2000);
    
    private static async Task MyAsyncFun2()
    
        await Task.Yield();
        System.Threading.Thread.Sleep(2000);
    
    public async Task<ApiResult> MyAction([FromBody] Mymodel model)
    
        DateTime time1 = DateTime.Now;
        Task task1 = MyAsyncFun1();
        Task task2 = MyAsyncFun2();
        task1.Wait();
        task2.Wait();
        DateTime time2 = DateTime.Now;
        double d=(time2 - time1).TotalSeconds;
        return .....;
    

执行在 task1.Wait() 语句上无限期挂起。

【问题讨论】:

我不明白 DI 与此有什么关系,当您可以在异步方法中 await 时,您为什么要 Wait() "不要阻塞异步代码" > 永远不要在 async Task 方法上使用 .Wait() 我看这里没有依赖注入? 控制台应用程序没有同步上下文。 asp.net 确实(无论如何都是“旧”asp.net。我相信他们已经为 asp.net 核心消除了它) @GerriePretorius - 他正在使同步上下文陷入僵局。这类问题的例子太多了,我认为构建另一个指出这一点的答案没有任何价值。 【参考方案1】:

您的代码可能在 ASP.NET(而不是 ASP.NET Core)中运行,并且具有需要独占访问权限的 SynchronizationContext,当您阻塞异步代码时,您可能会出现死锁,就像您在此处所做的那样。

这里发生的情况是,按时间顺序,您的第一个等待的不完整任务发生在 MyAsyncFun1 中,等待 Task.Yield(),这会立即返回一个不完整的任务,稍后会将继续(睡眠)发布回当前的 SynchronizationContext

稍后你在task1 上调用.Wait(),它会阻塞直到它完成,但是它需要SynchronizationContext 可用,但是你等待的阻塞线程正在使用它,所以这是一个僵局,死锁。

您可以在等待的任务上使用.ConfigureAwait(false),以确保它们不需要将延续发布回当前的SynchronizationContext,但更好的方法当然是在任何地方等待,并使用异步顶部- 到底部。

【讨论】:

以上是关于c#异步方法不起作用[重复]的主要内容,如果未能解决你的问题,请参考以下文章

功能推送的异步/等待不起作用[重复]

从 Alamofire 附加数据不起作用 [重复]

SpringBoot异步任务及Async不起作用的原因

剪贴板在 C# 控制台应用程序上不起作用 [重复]

Xamarin 中的 NUnit 异步测试不起作用

连接字符串不起作用[重复]