0

Per my understanding the Parallel.Foreach block the calling thread until it completes. However, the below code behave differently --

private void TestParallel()
{
            Console.WriteLine("Starting TestParallelForEach");
            TestParallelForEach();
            Console.WriteLine("Ending TestParallelForEach");
}

public void TestParallelForEach()
{
            List<string> urls = new List<string>();
            urls.Add("http://www.google.com");
            urls.Add("http://www.yahoo.com");
            urls.Add("http://www.microsoft.com");
            urls.Add("http://www.facebook.com");

            var t = Parallel.ForEach(
                urls,
                new ParallelOptions { MaxDegreeOfParallelism = 1 },
                async url =>
                {
                    string x = await openUrlAsync(url);
                    Console.WriteLine(string.Format("Url {0}, result {1}", url, x));
                });

            Console.WriteLine(" Parallel.ForEach Completed - " + t.IsCompleted);
   }



private async Task<string> openUrlAsync(string url)
{
        var client = new HttpClient();
        //var result = await client.GetAsync("http://webcode.me");
        var result = await client.GetAsync(url);
        string re = result.StatusCode.ToString();

        Console.WriteLine(string.Format("Got response from Url {0}", url));
        return re;
 }

However, the output of the above code is as follows --
Starting TestParallelForEach
Parallel.ForEach Completed - True
Ending TestParallelForEach
Got response from Url www.facebook.com
Url www.facebook.com, result OK
Got response from Url www.stanford.edu
Url www.microsoft.com, result OK

My expectation was the output should be in the below order since Parallel.Foreach block the calling thread until it completed.
Starting TestParallelForEach
Got response from Url www.facebook.com
Url www.facebook.com, result OK
Got response from Url www.stanford.edu
Url www.microsoft.com, result OK
Parallel.ForEach Completed - True
Ending TestParallelForEach

I reckon I am missing something here ....why doesn't Parallel.Foreach waits till all it's internal tasks(the Http call here) are completed ?

Gautam Moulik
  • 85
  • 1
  • 7
  • drop `async`: `url => {...}` – Dmitry Bychenko Feb 20 '20 at 08:04
  • It looks like you aren't awaiting `ForEach` function. Also `Parallel.ForEach` is useless if it has `MaxDegreeOfParallelism = 1` – Bukk94 Feb 20 '20 at 08:05
  • @Shocky would be interesting to see how you implement your suggestion to "awaiting ForEach"... – Alexei Levenkov Feb 20 '20 at 08:07
  • @AlexeiLevenkov I'm not suggesting awaiting foreach (but if you make a list of tasks and then waitall then it would be plausible), but since he has async function, it needs to be awaited to be able to get results he wants. I would probably go with different approach than this. – Bukk94 Feb 20 '20 at 08:12
  • `Parallel.ForEach` is neither async friendly, nor suitable for throttling I/O operations. Look here for proper solutions: [How to limit the amount of concurrent async I/O operations?](https://stackoverflow.com/questions/10806951/how-to-limit-the-amount-of-concurrent-async-i-o-operations) – Theodor Zoulias Feb 20 '20 at 08:47

0 Answers0