创建数千个 Web 请求任务并使用 Task.WhenAll() 等待它们是否安全

问题描述 投票:0回答:2

我有一个 Web API 方法,它接受字符串列表,对每个字符串执行 Web 请求,并将所有数据编译到一个列表中以供返回。

输入列表的长度可以是可变的,最多可达数千个。我是否需要通过将并发任务分组来手动限制并发任务的数量,或者创建数千个任务并使用

Task.WhenAll()
等待它们是否安全?这是我现在使用的片段:

public async Task<List<Customer>> GetDashboard(List<string> customerIds)
{
    HttpClient client = new HttpClient();
    var tasks = new List<Task>();
    var customers = new List<Customer>();

    foreach (var customerId in customerIds)  
    {
        string customerIdCopy = customerId;
        tasks.Add(client.GetStringAsync("http://testurl.com/" + customerId)
            .ContinueWith(t => {
                customers.Add(new Customer { Id = customerIdCopy, Data = t.Result });
            }));
    }

    await Task.WhenAll(tasks);

    return customers;
}
c# .net asynchronous async-await
2个回答
7
投票

HttpClient
可以有效地执行并发请求,但需要注意的是它限制了单个服务器的并发请求数量。

如果您的请求全部发送到同一个站点,则多余的请求将被放入队列中。当请求在此队列中时,请求超时会逐渐减少......在尝试连接到服务器之前。因此,请小心管理,如果合适的话甚至可以关闭超时。

除此之外,一次发起数千个请求也是完全可以的。

如果您认为这会影响您,您可以使用

SemaphoreSlim
或 TPL 数据流来限制并发请求的数量。


-1
投票

首先想到的是将所有“多线程性能”部分委托给 TPL。在您的请求中使用

async
,而不是手动创建的任务和
ContinueWith

它还将使 C# 关心线程性能。

private async Task<Customer> GetDashboardAsync(string customerId) 
{
    using (var httpClient = new HttpClient())
    {
        string data = await httpClient.GetStringAsync("http://testurl.com/" + id);
        return new Customer { Id = id, Data = data });
    }
}

public async Task<Customer[]> GetDashboardAsync(List<string> customerIds)
{
    var tasks = customerIds
        .Select(GetDashboardAsync)
        .ToArray();

    return await Task.WhenAll(tasks);
}

我是否需要通过将并发任务分组来手动限制并发任务的数量,或者创建数千个任务并使用

Task.WhenAll()
等待它们是否安全?

如果您仅使用

List
foreach
ContinueWith
创建任务,则可能会因任务数量过多而导致性能下降。
但是,如果您在代码中使用了
async/await
,那么您就不需要担心它。 TPL 将使用异步任务和延续来提供最佳性能。
您可以尝试一下以确保它有效:)

© www.soinside.com 2019 - 2024. All rights reserved.