C# 在非异步操作中调用异步方法时发生死锁

C# 在非异步操作中调用异步方法时发生死锁,c#,asynchronous,asp.net-web-api,C#,Asynchronous,Asp.net Web Api,我们有一个web应用程序,它由UI使用的web API组成。web应用程序安装在不同的服务器上(在客户端安装之前进行测试) 在一台服务器上,我们通过以下端点获得死锁: [HttpGet, Route(Order = 1)] public IHttpActionResult GetUserDetails(long userKey) { var userService = ResolveService<IUserService>(); var nameService =

我们有一个web应用程序,它由UI使用的web API组成。web应用程序安装在不同的服务器上(在客户端安装之前进行测试)

在一台服务器上,我们通过以下端点获得死锁:

[HttpGet, Route(Order = 1)]
public IHttpActionResult GetUserDetails(long userKey)
{
    var userService = ResolveService<IUserService>();
    var nameService =  ResolveService<INameService >();

    LoggInfo("Start userService.Get()"); //logged in logs
    var result = userService.Get(userKey);
    this.LoggInfo($"End userService.Get() with id = "{result.Id}); // logged in logs

    try
    {
      LoggInfo($"Start nameService.Get()"); // logged in logs
      result.Name =  nameService.Get(result.Namekey).Result?.Name;
      LoggInfo($"End nameService.Get()"); // not logged in logs
    }
   catch(Exception ex)
   {
     LogError("An error occured in NameService"); // not logged in logs
   }

    return Ok(result);
}
当我删除异步签名时,一切都正常工作,根据我的理解,死锁是正常的

你能解释一下为什么这在其他服务器上有效吗

提前谢谢你的帮助

你能解释一下为什么这在其他服务器上有效吗

为了实现这一目标,有三个必要部分:

  • 一次一个线程的上下文,所有服务器都将具有该上下文(预核心ASP.NET上下文)
  • 一个
    await
    (不带
    ConfigureAwait(false)
    )命令
  • 在该上下文中阻塞线程的代码,等待async方法完成。所有服务器都有这个功能
  • 最有可能的是,行为上的差异是由于第二部分:异步操作的
    wait

    具体地说,如果从
    GetAsync
    返回的
    任务在调用代码命中
    结果之前完成,就会发生这种情况。这必须非常快,但也可能取决于缓存、网络跳速、加载/邻居/防病毒等因素对代码的影响程度

    你能解释一下为什么这在其他服务器上有效吗

    为了实现这一目标,有三个必要部分:

  • 一次一个线程的上下文,所有服务器都将具有该上下文(预核心ASP.NET上下文)
  • 一个
    await
    (不带
    ConfigureAwait(false)
    )命令
  • 在该上下文中阻塞线程的代码,等待async方法完成。所有服务器都有这个功能
  • 最有可能的是,行为上的差异是由于第二部分:异步操作的
    wait


    具体地说,如果从
    GetAsync
    返回的
    任务在调用代码命中
    结果之前完成,就会发生这种情况。这必须非常快,但也可能取决于缓存、网络跳跃的速度、加载/邻居/防病毒等降低了多少代码速度。

    为什么不将
    GetUserDetails
    async,然后在异步调用中使用适当的等待语法?这是
    query.Select(MapName()).FirstOrDefaultAsync(n=>n.Key==Key)
    在死锁服务器上没有同步完成,在其他服务器上也没有同步完成?@Mason,我知道上面的方法不好,我只是想了解为什么有时有效,有时无效。@PetSerAi,是的,这就是问题所在,请注意,查询不需要很多时间(当我在sql developer中运行生成的查询时),为什么不将
    GetUserDetails
    async,然后在异步调用上使用正确的等待语法呢?这是
    query.Select(MapName()).FirstOrDefaultAsync(n=>n.Key==Key)
    在死锁服务器上没有同步完成,在其他服务器上也没有同步完成?@Mason,我知道上述方法不好,我只是想了解为什么有时有效,有时无效。@PetSerAi,是的,这就是问题所在,请注意,查询并不需要很多时间(当我在sql developer中运行生成的查询时)我添加了一些日志,我想你从来没有调用过它,知道吗?@BilelChaouadi:好吧,如果从来没有调用过它,那么它就永远不会死锁……那么会是什么呢,我已经包装了对nameService.Get()的调用在try catch中,我在catch块中添加了一些日志,但没有记录任何错误!!@BilelChaouadi:我不明白你在问什么。我已经更新了我的问题,问题是我的端点没有响应,在nameService中没有日志,也没有发生错误,似乎是nameService。Get never Hitted我添加了一些日志我想你从来没有打过电话,知道吗?@BillelChaouadi:好吧,如果从来没有打过电话,那么它就永远不会死锁……那可能是什么呢,我已经结束了对名称服务的调用。Get()在try-catch中,我在catch块中添加了一些日志,但没有记录任何错误!!@BilelChaouadi:我不明白你在问什么。我已经更新了我的问题,问题是我的端点没有响应,在nameService中没有日志,也没有发生错误,似乎nameService。从未命中
    public async Task<NameDTO> GetAsync(long key)
    {
        LogInfo("start NameService.Get()"); // not logged in logs
        var query = GetQuery();
        var name = await query.Select(MapName())
                              .FirstOrDefaultAsync(n => n.Key == key);
    
        return name;
    }