使用PLINQ导致OutofMemory异常而不是LINQ?

时间:2012-02-07 17:06:05

标签: c# plinq

我遇到过这样的情况,使用LINQ工作正常,但PLINQ导致“OutOfMemoryException”。以下是示例代码

   static void Main(string[] args)
    {
        Stopwatch timer = new Stopwatch();

        var guidList = new List<Guid>();
        for (int i = 0; i < 10000000; i++)
        {
            guidList.Add(Guid.NewGuid());
        }
       timer.Start();

        // var groupedList = guidList.GroupBy(f => f).Where(g => g.Count() > 1);
        var groupedList = guidList.AsParallel().GroupBy(f => f).Where(g => g.Count() > 1);
        timer.Stop();

        Console.WriteLine(string.Format("Took {0} ms time with result: {1} duplications", timer.ElapsedMilliseconds, groupedList.Count()));
        Console.ReadKey();
    } 

抛出内部异常“抛出类型'System.OutOfMemoryException'的异常”......可能是什么问题?在这种情况下使用PLINQ的准则是什么,提前谢谢。

2 个答案:

答案 0 :(得分:3)

您可能接近常规Linq版本的内存不足,但使用AsParallel()会增加额外的分区开销以并行运行,因此您可以超出限制。

当我尝试你的样本时,我首先得到了相同的结果,非并行版本将完成,但PLinq版本将耗尽内存 - 将Guid列表大小加倍然后导致两个版本内存不足。另请注意,1000万Guids在内存中占用大约152 MB的空间

另请注意,您当前的plinq和linq查询仅在Console.WriteLine()中执行 - 因为Linq很懒,您必须强制进行评估,即使用ToList()(或在您的情况下Count()

答案 1 :(得分:2)

至少抑制问题的一种方法是不将所有guid放入列表中,而是使用可枚举的。

public IEnumerable<Guid> getGuids(int number)
{
    for (int i = 0; i < number; i++)
    {
        yield return Guid.NewGuid();
    }
}

这有几个优点。首先,它是懒洋洋地加载的,所以你在处理过程中失败而不是guids的声明。其次,你并没有抓住所有未通过where子句的guid;它们可以从内存中删除。这意味着很多。你只需要在内存中拥有每个guid的一个副本,而不是在你点击where子句时有两个副本。