0

我有一个IEnumerable我想对其进行处理的对象。但是当集合变得太大时,它会OutOfMemoryException在枚举它时抛出一个,例如在调用Count().

显而易见的解决方案是将集合拆分为多个部分,以使每个部分都不会太大。但我不知道每个部分中理想的对象数量是多少,并且我想避免“幻数”,因为我不知道每个对象的潜在大小。我什至不知道将它分成多个部分是否是一个好的解决方案。有任何想法吗?

编辑:

在我的代码中,我有这个功能。请注意将Select项目MyData放入包装对象的集合中,这会增加大小。当枚举这个集合时,我得到了异常(我可以messages.Select(m => new CloudQueueMessage(m.ToBinary())).ToList()立即得到异常)。

    public static void AddMessages(IEnumerable<MyData> messages)
    {
        DoStuff(messages.Select(m => new CloudQueueMessage(m.ToBinary())));
    }
4

3 回答 3

3

Enumerable.Count()如果它是一个查询而不是一个集合,它会枚举序列以获取它的计数(然后它正在使用该Count属性)。然而,即使它枚举了它不应该抛出的序列,OutOfMemoryException因为它不会创建新的东西。

我假设您正在使用在Count(). ToList()如果你使用or ,你也会得到例外ToArray()。因此,您需要向我们展示查询,我们可以尝试在内存消耗方面对其进行优化。

于 2013-04-17T10:24:25.330 回答
3

使用MoreLINQ 的批处理扩展方法,即“将源序列批处理为大小桶”。示例如下:

int batchSize = 1000;

var lotsOfItems = Enumerable.Range(0, 10000000);
var batched = lotsOfItems.Batch(batchSize); 

foreach (var batch in batched)
{
    //handle each batch
}
于 2013-04-17T10:23:37.640 回答
0

尝试这个

public IEnumerable<IEnumerable<T>> GetPortions<T>(IEnumerable<T> list, int portion)
{
   double length = (list.Count() / (double)portion); 

   for (int i = 0; i < length; i++)
   {
         yield return list.ToList().Skip(i * portion).Take(portion);
   } 
}

protected void Page_Load(object sender, EventArgs e)
{ 
    IEnumerable<int> list = Enumerable.Range(1, 25); 

    foreach (var item in GetPortions(list, 10))
    {

    }
 }
于 2013-04-25T11:15:07.650 回答