C# ASP.NET核心控制器中奇怪的死锁情况
在我的ASP.NET核心应用程序中,我有一个看似非常简单的操作。它等待异步方法的某个值,然后将其作为OK结果返回:C# ASP.NET核心控制器中奇怪的死锁情况,c#,asp.net-core,async-await,task-parallel-library,deadlock,C#,Asp.net Core,Async Await,Task Parallel Library,Deadlock,在我的ASP.NET核心应用程序中,我有一个看似非常简单的操作。它等待异步方法的某个值,然后将其作为OK结果返回: public async Task<IActionResult> GetNextCommand() { var command = await LongPollManager.Instance.GetNextCommand(HttpContext.RequestAborted); return Ok(command); } public异步任务GetN
public async Task<IActionResult> GetNextCommand()
{
var command = await LongPollManager.Instance.GetNextCommand(HttpContext.RequestAborted);
return Ok(command);
}
public异步任务GetNextCommand()
{
var命令=await LongPollManager.Instance.GetNextCommand(HttpContext.RequestAborted);
返回Ok(命令);
}
当我使用某个HTTP客户端调用此路由时,我可以在调试器中验证此异步方法是否返回所需的值并将其传递给Ok方法:
如果让调试器继续运行,我希望在HTTP客户机中得到结果。但客户端从未收到响应
当我然后中断调试器时,我可以看到线程在一些内部锁上被阻塞。您可以在当前屏幕截图中看到:
只有在我对我的LongPollManager
类做了一些更改后,才能看到这种行为(该类实际上非常复杂,在内部使用TaskCompletionSource
s和concurrentdirectionarie
s以及SemaphoreSlim
s)
让我困惑的是,实际上阻塞的不是我自己的GetNextCommand
方法,而是ASP.NET内核中的阻塞。一旦执行到第29行,我得到了我的命令
对象,我的LongPollManager
类中所有复杂的异步工作都结束了,我看不出我在LongPollManager
中所做的任何更改是如何阻止ASP.NET Core正确完成请求的
ASP.NET核心在这里等待什么?我的代码(在没有死锁的情况下运行到第29行)如何导致这种死锁情况?如注释中所述 但在我最新的更改中,它还包含一个公共
任务属性。当ASP.NET内核尝试序列化它时,您认为这会有任何副作用吗
是的,会的
框架将尝试调用该属性以获取序列化的值。当属性返回一个任务
,它很可能会尝试同步序列化任务的结果
属性,这将导致死锁
混合使用异步和阻塞调用,如.Result
和.Wait()
,可能会导致死锁,应该避免
参考文献
操作应该返回简单的POCO,在序列化时没有副作用
公共任务
属性应该对serailizer隐藏,通过属性忽略,或者应转换为在序列化模型时不会调用的方法。客户端如何进行调用客户端是同一台机器上的另一个进程在该路由上执行HTTP get。模型是否返回POCO,或者序列化时是否会调用任何连锁反应。要点-它过去只包含string
s和bool
s。但在我最新的更改中,它还包含一个公共任务属性。当ASP.NET Core尝试序列化它时,您认为这会有任何副作用吗?是的。因为它将尝试调用属性以获取要序列化的值。由于这是一个带有的任务,您很可能会尝试同步序列化Task.Result
,这将导致死锁。