我创建了一个类来处理多个 HTTP GET 请求。它看起来像这样:
public partial class MyHttpClass : IDisposable
{
private HttpClient theClient;
private string ApiBaseUrl = "https://example.com/";
public MyHttpClass()
{
this.theClient = new HttpClient();
this.theClient.BaseAddress = new Uri(ApiBaseUrl);
this.theClient.DefaultRequestHeaders.Accept.Clear();
this.theClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<JObject> GetAsync(string reqUrl)
{
var returnObj = new JObject();
var response = await this.theClient.GetAsync(reqUrl);
if (response.IsSuccessStatusCode)
{
returnObj = await response.Content.ReadAsAsync<JObject>();
Console.WriteLine("GET successful");
}
else
{
Console.WriteLine("GET failed");
}
return returnObj;
}
public void Dispose()
{
theClient.Dispose();
}
}
然后,我通过在 Task.Run() 上使用循环,然后在 Task.WaitAll() 之后以以下方式对多个请求进行排队:
public async Task Start()
{
foreach(var item in list)
{
taskList.Add(Task.Run(() => this.GetThing(item)));
}
Task.WaitAll(taskList.ToArray());
}
public async Task GetThing(string url)
{
var response = await this.theClient.GetAsync(url);
// some code to process and save response
}
它的工作速度肯定比同步操作快,但没有我预期的那么快。根据其他建议,我认为本地线程池正在减慢我的速度。 MSDN 建议我应该将其指定为长时间运行的任务,但我找不到像这样调用它的方法。
现在我还没有限制线程,我只是进行批量处理和测试速度以发现正确的方法。
有人能给我建议一些可以提高速度的领域吗?
最佳答案
所以,在您设置 DefaultConnectionLimit 后一个很好的高数字,或者只是管理与您正在访问的主机的连接的 ServicePoint 的 ConnectionLimit:
ServicePointManager
.FindServicePoint(new Uri("https://example.com/"))
.ConnectionLimit = 1000;
唯一可疑的代码是你开始一切的地方......
public async Task Start()
{
foreach(var item in list)
{
taskList.Add(Task.Run(() => this.GetThing(item)));
}
Task.WaitAll(taskList.ToArray());
}
这可以减少到
var tasks = list.Select(this.GetThing);
创建任务(您的异步方法返回热(运行)任务...无需使用Task.Run
双重换行)
然后,不要在等待它们完成时阻塞,而是异步等待:
await Task.WhenAll(tasks);
关于c# - 优化异步HttpClient请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30158008/