Parallel.For使用step!= 1

有没有办法实现这个for循环的Parallel.For版本?

 for (int i = 0; i < 100; i += 2) { DoStuff(i); } 

我没有看到接受步骤参数的重载,但我想不出任何理由这在逻辑上是不可能的。

对此和此问题的接受答案建议在使用Enumerable.Range生成的一系列int上使用Parallel.ForEach ,但在我的情况下,我使用线程本地数据, 因此Parallel.ForEach不是一个选项

另一种选择是检查我的循环体中是否i % 2 == 0return ,但这仍然执行线程本地数据初始化器Func和终结器Func 。 以下是演示此选项的代码段:

 Parallel.For(0, limit, () => new Bar(), //thread local data initialize (i, state, local) => //loop body { if (i % 2 != 0) return local; local.foo += DoStuff(i); return local; }, (local) => //thread local data post-action { lock (loopLocker) { globalData.foo += local.foo; ); } ); 

这是一个提示:

 for (int j = 0; j < 50; j++) { i = 2*j; DoStuff(); } 

通常,看看你是否可以计算出迭代次数以及从迭代次数到变量值的转换。

这是处理步进索引的另一种方法

 private void ParallelForEachProcessSteppedIndexes() { Parallel.ForEach(SteppedIterator(0, 100, 2), (index) => DoStuff(index)); } private static IEnumerable SteppedIterator(int startIndex, int endIndex, int stepSize) { for (int i = startIndex; i < endIndex; i = i + stepSize) { yield return i; } } 

Ben的建议非常适合恒定步骤,例如+ 2,+ 3等。

或者(如果您的步骤是随机的)您可以使用Parallel.ForEach例如

 int[] input = { 1, 3, 4, 5, 7, 10, 20, 25 }; Parallel.ForEach(input, () => new Bar(), //thread local data initialize (i, state, local) => //loop body { // your code }, (local) => //thread local data post-action { // your code } 

变量i将从input数组中获取数据。 您可以使用Enumerable.Range替换input (或将其与With等组合)

如果你想在i变量中只获得素数,那将完全正常。

转换为VB.NET的新Iterator函数后,Toan的答案对我有用

 Private Sub LoopExample() Parallel.ForEach(SteppedIterator(1,100,5), AddressOf Test) End Sub Private Iterator Function SteppedIterator(startIndex As Integer, endIndex As Integer, stepSize As Integer) As IEnumerable(Of Integer) For i As Integer = startIndex To endIndex Step stepSize Yield i Next End Function Private Sub Test(i As Integer, state As ParallelLoopState, index As Long) Debug.WriteLine(i.ToString) End Sub