这是有问题的代码:
var raw = Enumerable.Range(1, 10);
var candidates = raw.AsParallel();
var p1 = candidates.AsParallel()
.SelectMany(
ii =>
{
Debug.Log(">>>>> " + ii);
Thread.Sleep(1000);
// for each connection, setup a monitor stream
// immediately start reading it and ensure that >= 1 heartbeat is received in the first 2 seconds
// if not, connection is deemed invalid & closed
try
{
return new[] { 3 };
}
finally
{
Debug.Log("<<<<< " + ii);
}
}
);
var p2 = p1.Select(
(v, i) =>
{
if (i != 0) return 0;
return v;
}
);
var chosen = p2.FirstOrDefault();
执行后,它给出以下日志:
>>>>> 1
<<<<< 1
>>>>> 2
<<<<< 2
>>>>> 3
<<<<< 3
>>>>> 4
<<<<< 4
>>>>> 5
<<<<< 5
>>>>> 6
<<<<< 6
>>>>> 7
<<<<< 7
>>>>> 8
<<<<< 8
>>>>> 9
<<<<< 9
>>>>> 10
<<<<< 10
并花了10秒来执行。理论上,执行时应该需要 1 秒并立即达到
>>>>> x
。
此行为的原因是什么以及如何解决
SelectMany
的内部机制似乎影响了 PLINQ 处理数据的方式。 ParallelExecutionMode.ForceParallelism
似乎解决了它:
var candidates = raw.AsParallel()
.WithExecutionMode(ParallelExecutionMode.ForceParallelism);
var p1 = candidates
.SelectMany(...)