为什么在使用PLINQ Take()时会抛出OutOfMemoryException?

Pab*_*lla 6 c# out-of-memory plinq .net-4.5

升级到DotNet 4.5后,一个查询开始给我OutOfMemoryExceptions.

(提炼)查询是:

var tests = new int[]{}
    .AsParallel()
    .GroupBy(_ => _)
    .Take(int.MaxValue)
    .ToArray();
Run Code Online (Sandbox Code Playgroud)

我发布这个给同样问题的人.我将在下面回答.

Pab*_*lla 7

这似乎是框架的一个变化.

Take()运算符在TakeOrSkipQueryOperator内部类中实现.代码中有一个分支通过WrapHelper()函数创建一个FixedMapHeap实例,该实例又创建了一个Key元素数组,该元素的大小最初传递给Take()(在给定的示例中,它将是一个8Gb的数组) ).

  • 在很多时候听起来像是一个合理的优化 - 应该允许在很多情况下更好的并行化,因为不同的线程可以写入该堆的不同部分而没有相互干扰的风险.在这种情况下,这种情况很明显. (3认同)