我有大约500万个项目需要更新。我不太在乎响应(有响应会很好,所以我可以记录下来,但是我不希望这样会浪费我的时间。)话虽如此,此代码是否经过优化可按以下方式运行尽可能快?如果有500万件物品,我是否会有取消任何任务或超时错误的风险?我每秒收到大约1或2个回复。
var tasks = items.Select(async item =>
{
await Update(CreateUrl(item));
}).ToList();
if (tasks.Any())
{
await Task.WhenAll(tasks);
}
private async Task<HttpResponseMessage> Update(string url)
{
var client = new HttpClient();
var response = await client.SendAsync(url).ConfigureAwait(false);
//log response.
}
更新:
我实际上正在获取TaskCanceledExceptions。我的系统是否耗尽了线程?我应该怎么做才能避免这种情况?
最佳答案
您的方法将同时启动所有任务,这可能不是您想要的。因为async
操作There is no thread,所以不会涉及任何线程,但是并发连接数可能会有所限制。
可能会有更好的工具来执行此操作,但是如果要使用async/await,则一种选择是使用this article中记录的Stephen Toub的ForEachAsync
。它允许您控制要执行的同时操作数量,因此不会超出连接限制。
这里是文章的内容:
public static class Extensions
{
public static async Task ExecuteInPartition<T>(IEnumerator<T> partition, Func<T, Task> body)
{
using (partition)
while (partition.MoveNext())
await body(partition.Current);
}
public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
return Task.WhenAll(
from partition in Partitioner.Create(source).GetPartitions(dop)
select ExecuteInPartition(partition, body));
}
}
用法:
public async Task UpdateAll()
{
// Allow for 100 concurrent Updates
await items.ForEachAsync(100, async t => await Update(t));
}