【问题标题】:Running into deadlocks code using AsyncContext使用 AsyncContext 遇到死锁代码
【发布时间】:2020-01-17 21:31:33
【问题描述】:

这是我的代码,我在我的库中使用 AsyncEx 来尝试绕过潜在的死锁,但我最终还是进入了那里:

return AsyncContext.Run(async () =>
{
   var get = await httpClient.GetAsync(url);
   if (get.IsSuccessStatusCode && (get.StatusCode == HttpStatusCode.OK))
   {
      var content = await get.Content.ReadAsStringAsync();
      return content;
   }

   return "";
});

我从命令行应用程序运行它,连续调用多个不同的url 值,但在一个大的for 循环中同步。如果有足够多的调用,它最终会死在它的轨道上。我做错了吗?

【问题讨论】:

  • AsyncContext.Run 确实使用了线程池中的线程。它通常不会在循环中调用。所以我的第一个猜测是线程池耗尽?我不确定为什么你的代码首先使用AsyncContext.Run
  • @StephenCleary 我们有一个要求,我们无法解决创建同步调用的问题,HttpClient 比它的 .Net 同步替代方案System.Net.WebRequest 更新和更快。我不确定“通常不在循环中调用”是什么意思,它是一个接受Task<T> 并返回T 的函数,为什么调用它的方式很重要?此外,如果AsyncContext.Run is 将在传入的任务完成之前返回(如果是,它返回什么?),那么线程池耗尽是有意义的,这样循环的下一次迭代被调用并导致一个新线程被获取。
  • 如果它的工作方式是 1) 抓取一个线程 2) 旋转等待 Task 完成,3) 返回线程,然后 4) 将结果返回到调用者,那么即使在无限循环中调用它,我也不会关注它如何抓取多个线程。
  • AsyncContext 为异步操作提供单线程上下文。它最常用于控制台应用程序的主线程,有时用于单元测试。我从未编写(或见过)一个应用程序使用多个。如果您使用的是控制台应用程序并且正在执行异步同步,为什么不直接使用GetAwaiter().GetResult()
  • 我在控制台应用程序中一次只使用一个。 GetAwaiter().GetResult() 也会冻结,这就是寻找需要 Task<T> 并返回 T 的东西的动力。

标签: c# nito.asyncex


【解决方案1】:

我认为发生的情况是,在调用 GetAsync 后,延续无法切换回同一个线程,因为另一个线程正在等待延续开始。下面的代码能用吗?

return AsyncContext.Run(async () =>
{
   var get = await httpClient.GetAsync(url).ConfigureAwait(false);
   if (get.IsSuccessStatusCode && (get.StatusCode == HttpStatusCode.OK))
   {
      var content = await get.Content.ReadAsStringAsync().ConfigureAwait(false);
      return content;
   }

   return "";
});

【讨论】:

  • 好吧,我仍然得到……一些……很奇怪的东西。我在async () 函数中添加了一些日志记录,以尝试查看它是否总是在同一个地方卡住。在await httpClient.GetAsync... (1) 之前,然后在 (2) 之后,然后在 await get.Content.Read... (3) 之后。我运行它,它看起来像 1、2、3、1、2、3、1、2、3、1,它停在那里。然后,过了一会儿,我连续得到几个 1,这应该是不可能的。关键是这是阻塞的,在循环中被调用。最终,实际上,它会解除阻塞并完成。
  • 我在一个不喜欢 jsfiddle/pastebin 的地方,所以我必须使用this。如果它过期了,请告诉我,我会放一个新的。
  • 我的意思是包括主函数在内的整个代码。如何调用此代码很重要。
  • 很公平,我在堆栈here 中包含了更多代码。它还有更多内容,但将其删除,因为在这种情况下它是未执行的噪音。
  • 建议避免在您的项目中使用任何预发布库:github.com/StephenCleary/AsyncEx/issues/107 它应该在一些并不总是满足的假设下工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多