繁体   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