c# - 使用异步/等待和任务优化即发即忘

标签 c# .net multithreading asynchronous async-await

我有大约 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,一个选择是使用 Stephen Toub 的 ForEachAsync,如 this article 中所述。 。它允许您控制要执行的同时操作数,这样您就不会超出连接限制。

这是文章中的内容:

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));  
}

关于c# - 使用异步/等待和任务优化即发即忘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25520254/

相关文章:

c++ - 为什么C++线程/future开销这么大

c# - .NET 6 在 Web API 项目 Controller 中使用 HTTP 客户端进行 API 调用

c# - CLR 会检查整个继承链以确定调用哪个虚方法吗?

c# - 为什么我的 SQL 查询返回重复的结果?

C# Xml 反序列化 - 保留子顺序

C# 从 CancellationToken.Register 中抛出 OperationCanceledException

java - 使用 TextArea.append() 时出现 NullPointerException

java - 难道每个线程都不需要自己的 JVM 副本吗?

c# - 按下控制键时 RichTextBox 选择错误

c# - 使用 == 比较两个结构