C# 在非异步操作中调用异步方法时发生死锁
我们有一个web应用程序,它由UI使用的web API组成。web应用程序安装在不同的服务器上(在客户端安装之前进行测试) 在一台服务器上,我们通过以下端点获得死锁: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 =
[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);
}
当我删除异步签名时,一切都正常工作,根据我的理解,死锁是正常的
你能解释一下为什么这在其他服务器上有效吗
提前谢谢你的帮助
你能解释一下为什么这在其他服务器上有效吗
为了实现这一目标,有三个必要部分:
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;
}