簡體   English   中英

如何為 Parallel.ForEachAsync 設置最小並行度

[英]How To Set Minimum Degree Of Parallelism For Parallel.ForEachAsync

假設我有以下 C# 代碼,它並行發送對某些 url 數組的獲取請求:

    internal class Program
    {
        static async Task Main(string[] args)
        {
            string[] urls = { "https://example1.com", "https://example2.com", "https://example3.com", "https://example4.com", "https://example5.com" };
            HttpClientHandler clientHandler = new HttpClientHandler();
            using (var client = new HttpClient(clientHandler))
            {
                client.Timeout = TimeSpan.FromSeconds(10);
                var options = new ParallelOptions { MaxDegreeOfParallelism = urls.Length };
                await Parallel.ForEachAsync(urls, options, async (url, stoppingToken) =>
                {
                    try
                    {
                        Console.WriteLine("Processing " + url);
                        HttpResponseMessage response = await client.GetAsync(url);
                        response.EnsureSuccessStatusCode();
                        var resp = await response.Content.ReadAsStringAsync();
                        Console.WriteLine("Response for " + url + " " + resp);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Response for " + url + " " + ex.Message);
                    }
                });
                Console.WriteLine("Completed");
            }
            Console.ReadLine();
        }
    }

如果我將 MaxDegreeOfParallelism 設置為數組的大小,這是否也作為隱含的最小並行度? 意思是,我的代碼會嘗試生成與 MaxDegreeOfParallelism 值相同數量的線程嗎?

編輯 1

如果沒有,我可以用下面的代碼實現類似的東西嗎:

    internal class Program
    {
        public async Task sendRequest(string url)
        {
            HttpClientHandler clientHandler = new HttpClientHandler();
            using (var client = new HttpClient(clientHandler))
            {
                client.Timeout = TimeSpan.FromSeconds(10);
                try
                {
                    Console.WriteLine("Processing " + url);
                    HttpResponseMessage response = await client.GetAsync(url);
                    response.EnsureSuccessStatusCode();
                    var resp = await response.Content.ReadAsStringAsync();
                    Console.WriteLine("Response for " + url + " " + resp);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Response for " + url + " " + ex.Message);
                }
            }
        }
        static async Task Main(string[] args)
        {
            string[] urls = { "https://example1.com", "https://example2.com", "https://example3.com", "https://example4.com", "https://example5.com" };
            foreach (string url in urls)
            {
                Program program = new Program();
                //dont await the sendRequest() method so that you can go through whole loop
                Thread operation = new Thread(() => program.sendRequest(url));
                operation.Start();
            }
            Console.ReadLine();
        }
    }

MaxDegreeOfParallelism 到數組的大小,這是否也作為隱含的最小並行度?

不。沒有“最小並行度”,因為即使在單核 CPU 上,代碼仍應運行。

我的代碼會嘗試生成與 MaxDegreeOfParallelism 值相同數量的線程嗎?

不,允許使用與MaxDegreeOfParallelism一樣多的線程,但不是必須的。 使用比邏輯 CPU 內核更多的線程對於計算受限的工作負載來說效率低下,因此它會盡量保持線程數盡可能小,同時仍然使用盡可能多的 CPU,但我不確定具體細節。 除非您有其他原因,否則我建議您不要設置MaxDegreeOfParallelism並讓循環使用其默認行為。

請注意,並行循環的主要好處是在運行計算綁定代碼時。 您的示例似乎嚴格受 IO 約束,因此可能不會比使用這樣的方法獲得太多好處:

await Task.WhenAll(urls.Select(async url => {...}));

這將順序啟動所有請求,讓請求並發運行,然后再次順序處理結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM