简短版:在循环中调用数千次异步方法,并且这些方法可能会调用其他异步方法时,异步调用的扩展性如何?线程池会爆满吗?
我一直在阅读和实验 TPL 和 Async,但在某些方面仍存在困惑,例如异步调用的扩展性。以下直奔主题。
异步调用 对于 IO,使用异步比新建线程/启动任务更好,但据我所知,在不使用不同线程的情况下执行异步操作是不可能的,这意味着异步必须在某个时刻使用其他线程/启动任务。 因此,我的问题是:相对于系统资源,代码 A 怎样比代码 B 更好?
代码 A
这让我想到了以下问题:
1 - 循环中应避免异步调用吗?
2 - 异步调用的最大合理数量是多少,或者任何数量的异步调用都可以吗?这如何扩展?
3 - 异步方法在底层每个调用是否启动任务?
我使用1000个URL进行测试,线程池工作线程的使用数量甚至没有达到30个,而IO完成线程的数量始终约为5个。 我的实际实验
我创建了一个带有简单异步控制器的网络应用程序。该页面由一个包含文本区域的表单组成,用户在其中输入希望请求/处理的所有URL。
提交后,使用HttpClient.GetUrlAsync方法在循环中请求URL,就像上面的代码A 一样。
有趣的是,如果我提交1000个URL,需要大约3分钟才能完成所有请求。
另一方面,如果我从3个不同的选项卡(即客户端)中的每个选项卡提交3个表单,每个表单中都有1000个URL,则结果需要更长时间(约10分钟),这真的让我感到困惑,因为根据MSDN的定义,它不应该花费比3分钟更长的时间,特别是即使在同时处理所有请求时,从线程池中使用的线程数也仅为25条,这意味着资源根本没有得到充分利用!
现在的工作方式使得这种类型的应用远非可扩展(假设我有大约5000个客户端一直请求一堆URL),而且我无法看到异步是如何发出多个IO请求的。
关于该应用程序的进一步说明
客户端:
1.用户进入网站
2.在文本区域中键入1000个URL
3.提交URL
服务器端:
1.接收URL数组
2.执行代码
我一直在阅读和实验 TPL 和 Async,但在某些方面仍存在困惑,例如异步调用的扩展性。以下直奔主题。
异步调用 对于 IO,使用异步比新建线程/启动任务更好,但据我所知,在不使用不同线程的情况下执行异步操作是不可能的,这意味着异步必须在某个时刻使用其他线程/启动任务。 因此,我的问题是:相对于系统资源,代码 A 怎样比代码 B 更好?
代码 A
// an array with 5000 urls.
var urls = new string[5000];
// list of awaitable tasks.
var tasks = new List<Task<string>>(5000);
HttpClient httpClient;
foreach (string url in urls)
{
tasks.Add(httpClient.GetStringAsync(url));
}
await Task.WhenAll(tasks);
Code B
...same variables as code A...
foreach (string url in urls)
{
tasks.Add(
Task.Factory.StartNew(() =>
{
// This method represents a
// synchronous version of the GetStringAsync.
httpClient.GetString(url);
})
);
}
await Task.WhenAll(tasks);
这让我想到了以下问题:
1 - 循环中应避免异步调用吗?
2 - 异步调用的最大合理数量是多少,或者任何数量的异步调用都可以吗?这如何扩展?
3 - 异步方法在底层每个调用是否启动任务?
我使用1000个URL进行测试,线程池工作线程的使用数量甚至没有达到30个,而IO完成线程的数量始终约为5个。 我的实际实验
我创建了一个带有简单异步控制器的网络应用程序。该页面由一个包含文本区域的表单组成,用户在其中输入希望请求/处理的所有URL。
提交后,使用HttpClient.GetUrlAsync方法在循环中请求URL,就像上面的代码A 一样。
有趣的是,如果我提交1000个URL,需要大约3分钟才能完成所有请求。
另一方面,如果我从3个不同的选项卡(即客户端)中的每个选项卡提交3个表单,每个表单中都有1000个URL,则结果需要更长时间(约10分钟),这真的让我感到困惑,因为根据MSDN的定义,它不应该花费比3分钟更长的时间,特别是即使在同时处理所有请求时,从线程池中使用的线程数也仅为25条,这意味着资源根本没有得到充分利用!
现在的工作方式使得这种类型的应用远非可扩展(假设我有大约5000个客户端一直请求一堆URL),而且我无法看到异步是如何发出多个IO请求的。
关于该应用程序的进一步说明
客户端:
1.用户进入网站
2.在文本区域中键入1000个URL
3.提交URL
服务器端:
1.接收URL数组
2.执行代码
foreach (string url in urls)
{
tasks.Add(GetUrlAsync(url));
}
await Task.WhenAll(tasks);
//at this point the thread is
// returned to the pool to receive
// further requests.
- 通知客户端工作已完成
请让我来为您解答!谢谢。