c#异步方法不起作用

时间:2018-04-03 11:46:29

标签: c# asp.net-web-api async-await

在使用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()语句中无限期挂起。

1 个答案:

答案 0 :(得分:1)

您的代码可能在ASP.NET(而不是ASP.NET Core)中运行,并且SynchronizationContext需要独占访问权限,当您阻止异步代码时,您可能会遇到死锁问题,就像您在这里一样。 / p>

这里发生的事情是,按时间顺序,您的第一个等待未完成的任务发生在MyAsyncFun1内部,等待Task.Yield(),这会立即返回一个不完整的任务,然后将延续(睡眠)发送回当前{{1} }。

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

您可以对正在等待的任务使用SynchronizationContext,以确保他们不要求将续约发布回当前.ConfigureAwait(false),但更好的当然是等待无处不在,并从上到下使用异步。