c# – parallel.foreach和httpclient – 奇怪的行为
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – parallel.foreach和httpclient – 奇怪的行为,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3041字,纯文字阅读大概需要5分钟。
内容图文
![c# – parallel.foreach和httpclient – 奇怪的行为](/upload/InfoBanner/zyjiaocheng/805/2dc23a05e65347d4b5fcedcbaebd8cab.jpg)
我有一段代码循环遍历集合,并为每次迭代调用httpclient. httpclient调用的api平均需要30-40ms才能执行.顺序调用它,我得到预期的结果,但是一旦我使用Parallel.foreach,它需要更长的时间.仔细查看日志,我可以看到很多httpclient调用需要1000ms才能执行,然后时间会回落到30-40ms.查看api日志,我可以看到它几乎没有超过100毫秒.我不知道为什么我会得到这个高峰.
代码是
using (var client = new HttpClient())
{
var content = new StringContent(parameters, Encoding.UTF8, "application/json");
var response = client.PostAsync(url, content);
_log.Info(string.Format("Took {0} ms to send post", watch.ElapsedMilliseconds));
watch.Restart();
var responseString = response.Result.Content.ReadAsStringAsync();
_log.Info(string.Format("Took {0} ms to readstring after post", watch.ElapsedMilliseconds));
}
并行调用是这样的
Console.WriteLine("starting parallel...");
Parallel.ForEach(recipientCollections, recipientCollection =>
{
// A lot of processing happens here to create relevant content
var secondaryCountryRecipientList = string.Join(",",refinedCountryRecipients);
var emailApiParams = new SendEmailParametersModel(CountrySubscriberApplicationId,
queueItem.SitecoreId, queueItem.Version, queueItem.Language, countryFeedItem.Subject,
countryFeedItem.Html, countryFeedItem.From, _recipientsFormatter.Format(secondaryCountryRecipientList));
log.Info(string.Format("Sending email request for {0}. Recipients {1}", queueItem.SitecoreId, secondaryCountryRecipientList));
var response = _notificationsApi.Invoke(emailApiParams);
});
谢谢
解决方法:
默认情况下,.NET每个服务器只允许2个连接.要更改此值,您必须将ServicePointManager.DefaultConnectionLimit的值更改为更大的值,例如20或100.
如果您发出太多请求,这不会阻止服务器泛滥或消耗太多内存.更好的选择是使用ActionBlock< T>缓冲请求并在受控功能中并行发送它们,例如:
ServicePointManager.DefaultConnectionLimit =20;
var client = new HttpClient();
var blockOptions=new ExecutionDataflowBlockOptions{MaxDegreeOfParallelism=10};
var emailBlock=new ActionBlock<SendEmailParametersModel>(async arameters=>
{
var watch=new Stopwatch();
var content = new StringContent(parameters, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
_log.Info(..);
watch.Restart();
var responseString = await response.Result.Content.ReadAsStringAsync();
_log.Info(...);
});
发送电子邮件不再需要并行调用:
foreach(var recipientCollection in recipientCollections)
{
var secondaryCountryRecipientList = string.Join(",",refinedCountryRecipients);
var emailApiParams = new SendEmailParametersModel(CountrySubscriberApplicationId, queueItem.SitecoreId, queueItem.Version, queueItem.Language, countryFeedItem.Subject,countryFeedItem.Html, countryFeedItem.From, _recipientsFormatter.Format(secondaryCountryRecipientList));
emailBlock.Post(emailApiParams);
log.Info(...);
}
emailBlock.Complete();
await emailBlock.Completion();
HttpClient是线程安全的,允许您对所有请求使用相同的客户端.
上面的代码将缓冲所有请求并一次执行10个请求.调用Complete()告诉块完成所有操作并停止处理新消息. await emailBlock.Completion()在继续之前等待所有现有消息完成
内容总结
以上是互联网集市为您收集整理的c# – parallel.foreach和httpclient – 奇怪的行为全部内容,希望文章能够帮你解决c# – parallel.foreach和httpclient – 奇怪的行为所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。