【发布时间】: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.Runis 将在传入的任务完成之前返回(如果是,它返回什么?),那么线程池耗尽是有意义的,这样循环的下一次迭代被调用并导致一个新线程被获取。 -
如果它的工作方式是 1) 抓取一个线程 2) 旋转等待
Task完成,3) 返回线程,然后 4) 将结果返回到调用者,那么即使在无限循环中调用它,我也不会关注它如何抓取多个线程。 -
AsyncContext为异步操作提供单线程上下文。它最常用于控制台应用程序的主线程,有时用于单元测试。我从未编写(或见过)一个应用程序使用多个。如果您使用的是控制台应用程序并且正在执行异步同步,为什么不直接使用GetAwaiter().GetResult()? -
我在控制台应用程序中一次只使用一个。
GetAwaiter().GetResult()也会冻结,这就是寻找需要Task<T>并返回T的东西的动力。
标签: c# nito.asyncex