Closed as not planned
Description
Description
I would expect the following to be a valid pattern, but it does not lead to parallel execution of ComputeExpensiveThing():
var resultsByItem = items.AsParallel().ToDictionary(i => i, i => ComputeExpensiveThing());
Reproduction Steps
var items = Enumerable.Range(0, 100).AsParallel();
var stopwatch = Stopwatch.StartNew();
// completes in ~10s because there is no parallelism
var dictionary = items.ToDictionary(i => i, i => { Thread.Sleep(100); return i; });
// workaround completes in ~1s
/*var dictionary = items.Select(i =>
{
Thread.Sleep(100);
return new KeyValuePair<int, int>(i, i);
})
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);*/
Console.WriteLine(stopwatch.Elapsed);
Expected behavior
From a parallelism perspective, I would expect
items.AsParallel().ToDictionary(i => ..., i => ...)
to be equivalent to:
items.AsParallel().Select(i => KeyValuePair.Create(..., ...)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
For example, ParallelEnumerable.Min()
parallelizes its selector:
Enumerable.Range(1, 10).AsParallel().Min(i => { Thread.Sleep(1000); return i; }); // completes in ~1s
Actual behavior
keySelector and elementSelector execute serially
Regression?
No response
Known Workarounds
As shown above, pushing any non-trivial selectors up one layer into a Select
call gets around the issue.
Configuration
.NET 8 Windows 11 x64
Other information
ParallelEnumerable.ToDictionary
has a serial loop in which the selectors are executed.