为什么 c# Parallel.ForEach 没有在我的 c# 应用程序中创建太多打开的连接?

Why is c# Parallel.ForEach not creating too many open connections in my c# app?

我的代码出现了一些问题,导致打开的连接太多,导致它们关闭并且得不到 http 响应。我已经重构为如下所示的内容:

List<<List<string>> batches = splitListOfUrlStringsIntoBatches(urls, 50); // where 50 is the batch size

然后我做:

foreach (var batchList in listOfBatchLists)
{
    var insertForBatch = RunBatch(batchList);
    allInsertAmounts.Add(insertForBatch);
}

和 运行 批次看起来像:

    private int RunBatch(IEnumerable<string> batch)
    {
        var allWriteNum = 0;
        // this will run on one bound logical thread i think
        Parallel.ForEach(batch, (batchItem) => {
             var res = Client.GetAsync(batchItem.Item1).GetAwaiter().GetResult();
             var responseBody = res.Content.ReadAsStringAsync().GetAwaiter().GetResult();            
             var strongType = JsonConvert.DeserializeObject<StrongType>(responseBody);

             dbContext.add(strongType);
             allWriteNum++
        });
        return allWriteNum;
    }

问题是,如果我将批量大小增加到 50,000 这样愚蠢的东西,我不会收到任何关闭的连接错误,现在我不确定为什么..

是否因为 Parallel.foreach 进行了优化以创建最佳数量的任务并且它可以以某种方式解决这样做会导致太多打开的连接?还是太多 cpu 工作?

您正在访问外部资源(通过 http 客户端)- IO 操作,这就是 async-await 的设计目的。

public async Task<StrongType> GetAsync(Item item)
{
    var response = await Client.GetAsync(item);
    var body = await response.Content.ReadAsStringAsync();  

    return JsonConvert.DeserializeObject<StrongType>(body);
}

public async Task Run(IEnumerable<Item> items)
{
    var tasks = items.Select(item => GetAsync(item));
    await Task.WhenAll(tasks);

    var loadedStrongTypes = tasks.Select(task => task.Result);
    dbContext.AddRange(loadedStrongTypes);
}

因为代码使用外部资源,并行方法会创建许多什么都不做的线程,只等待响应,从而浪费资源。
使用异步等待,您将能够发送所有请求而无需等待响应。
当所有响应都成功到达时,您可以继续处理接收到的数据。