2012-09-24 43 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); 
}