2012-09-24 19 views
0

rulesObjs批量调用Execute方法的好方法是什么?假设列表中有超过10,000个对象,并且我想一次调用Execute,每次不超过500个对象。拆分对象数组,然后分批处理

public static List<object> ExecutePolicy() 
    { 
     Policy policy = new Policy(); 

     List<object> rules = GetRules(); 

     object[] rulesObjs = rules.ToArray(); 

     // Call this method with array of object, but in batches. 
     policy.Execute(rulesObjs); 

     return rulesObjs.ToList(); 
    } 

    private static List<object> GetRules() 
    { 
     // get the rules via some process 
     return new List<object>(); 
    } 
} 

public sealed class Policy 
{ 
    public void Execute(params object[] rules) 
    { 
     // Process rules... 
    } 
} 

我对Execute()方法没有控制权。

+1

我认为你可以使用morelinq的[批量](http://code.google.com/p/morelinq/source /browse/MoreLinq/Batch.cs?r=f85495b139a19bce7df2be98ad88754ba8932a28)。 –

+1

如果'GetRules'返回一个'IEnumerable'而不是一个列表,L.B的建议将会更加有用,并且流式传输它的结果而不是急切地评估整个事情。 – Servy

+0

@Servy我说它不是性能明智的,只是为了更简洁的代码。它并不比在循环中为'Skip's和'Take'调用'GetEnumerator' –

回答

4
List<object> rules = GetRules(); 
int batchSize = 500; 
int currentBatch = 0; 

while (currentBatch * batchSize < rules.Count) 
{ 
    object[] nextBatch = rules.Skip(currentBatch * batchSize) 
     .Take(batchSize).ToArray(); 
    //use batch 
    currentBatch++; 
} 
+0

+1:这个问题的一个问题是,如果'rules.Count%batchSize'不是0,它会在'.Take(batchSize)' – VoodooChild

+0

@VoodooChild上抛出异常否。 “Take”是这样实现的,如果您尝试采集比集合更多的项目,它将仅返回那里的所有项目。 – Servy

+0

太棒了,我不知道 - 谢谢。 – VoodooChild

2

那么,如果你可以控制Execute()方法,那么最好的方法是将索引传递给该方法,以便知道该数组的哪个索引。

public void Execute(int startIndex, /*optional*/ int endIndex, params object[] rules) 
{ 
    // Process rules... 
} 

不要担心在一次传球太多的数据。在幕后,你的数组只是一个指针,所以你只是传递一个参考。


如果你没有在Execute()方法控制,那么你可以让你的部分新阵列,使用Array.Copy和过程,新的数组。

+0

我无法控制'Execute()'方法,更新了我的问题以指出它。 – VoodooChild

2

有了参考System.Linq你可以使用跳跃,并采取:

int total = 10000; 
int chunkSize = 500; 
for (int i = 0; i < total; i += chunkSize) 
{ 
    var chunk = rulesObjs.Skip(i).Take(chunkSize).ToArray(); 

    policy.Execute(chunk); 
}