【发布时间】:2018-03-18 07:22:37
【问题描述】:
在我的 ASP.NET Core 应用程序中,我有一个看似非常简单的操作。它等待来自异步方法的某个值,然后将其作为 OK 结果返回:
public async Task<IActionResult> GetNextCommand()
{
var command = await LongPollManager.Instance.GetNextCommand(HttpContext.RequestAborted);
return Ok(command);
}
当我使用一些 HTTP 客户端调用此路由时,我可以在调试器中验证此异步方法是否返回所需的值并将其传递给 Ok 方法:
如果我让调试器继续运行,我希望在我的 HTTP 客户端中得到结果。但是客户端永远不会收到响应。
当我中断调试器时,我可以看到线程被某个内部锁阻塞。您可以在当前的屏幕截图中看到这一点:
只有在我对 LongPollManager 类进行了一些更改后才能看到这种行为(这实际上非常复杂,并且在内部使用了 TaskCompletionSources 和 ConcurrentDictionaries,以及 SemaphoreSlims)。
令我困惑的是,实际上阻塞的不是我自己的GetNextCommand 方法,而是阻塞似乎发生在 ASP.NET Core 内部。一旦执行在第 29 行并且我得到了我的 command 对象,我的 LongPollManager 类的所有复杂异步内容都结束了,我看不出我在 LongPollManager 中所做的任何更改如何阻止 ASP.NET Core 正常运行完成请求。
ASP.NET Core 在这里等待什么?我的代码(运行到第 29 行没有死锁)怎么会导致这样的死锁情况?
【问题讨论】:
-
客户如何拨打电话
-
客户端是同一台机器上的另一个进程,在该路由上执行 HTTP GET。
-
返回的模型是 POCO 还是序列化时调用的任何连锁效应。
-
好点 - 它曾经只包含
strings 和bools。但随着我的最新更改,它还包含一个公共Task属性。当 ASP.NET Core 尝试序列化它时,您认为这会产生任何副作用吗? -
会的。因为它会尝试调用属性来获取要序列化的值。因为它是一个任务,很可能会尝试同步序列化
Task.Result,这会导致死锁。
标签: c# asp.net-core async-await task-parallel-library deadlock