我有大约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));
}

10-08 06:41
查看更多