提问者:小点点

C#异步方法不工作[重复]


考虑使用VS2015编写的控制台应用程序上的以下代码:

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()语句的执行无限期挂起。


共1个答案

匿名用户

您的代码大概是在ASP.NET(而不是ASP.NET核心)中运行的,并且有一个要求独占访问的,当您阻塞异步代码时,就有死锁的风险,就像这里所做的那样。

这里发生的事情是,按时间顺序,您等待的第一个未完成的任务发生在MyAsyncFun1中,等待,这将立即返回一个未完成的任务,并且稍后将继续(睡眠)发布回当前的

稍后您调用上的,这将阻塞直到它完成,但是它需要可用,但是您的等待阻塞线程正在使用它,所以这是一个僵局,死锁。

您可以在等待的任务上使用,以确保它们不需要将继续回发到当前的,但更好的当然是只在所有地方等待,并使用从上到下的异步。