2016-12-01 156 views
5

我可以改變我的循環改變for循環的Parallel.For循環

for (int i = 0; i < something; i++) 

到:

Parallel.For(0, something, i => 

但如何與這個循環?:

for (i = 3; i <= something/2; i = i + 2) 

由於這樣做尋求答案。

回答

7

由於

for (int i = 3; i <= something/2; i = i + 2) 
{ 
    ... 
} 

可改寫成

for (int k = 1; k < (something + 2)/4; ++k) 
{ 
    int i = 1 + 2 * k; 
    ... 
} 

你可以把

Parallel.For(1, (something + 2)/4, k => 
{ 
    int i = 1 + 2 * k; 
    ... 
}); 
3

第三個參數是delegate。因此,每次迭代都可以指定索引變量在委託中應該做些什麼。

編輯:好找到工作的解決方案: 由於已經由梅德Bychenko建議你還是應該從0開始,只需添加startValue作爲補償

int something = 16; 

int startValue = 3; 
int stepSize = 2; 

List<int> numbers = Enumerable.Range(0, 20).ToList(); 

Parallel.For(0, something/2, i => 
{ 
    int ind = (stepSize * i) + startValue ; Console.WriteLine(numbers[ind]); 
}); 
+1

這不符合他的要求。您的代碼並行運行值5,6,7,8,9,而他希望它等於跳過每個第二項(值:3,5,7)的循環。 –

+0

請注意,在'delegate'內更改'i'不會更改'Parallel.For'計數,它只是複製的值類型'int'。 –

+0

我明白了!你是完全正確的。 –

1

梅德Bychenko的回答得到它,但你也可以實現自己的ParallelFor與自定義步驟,這將使你的代碼有點更具可讀性:

static void ParallelFor(int start, int last, Func<int, int> step, Action<int> action) 
{ 
    var enumerable = StepEnumerable<int> 
     .Create(start, step) 
     .TakeWhile(x => x < last); 

    Parallel.ForEach(enumerable, action); 
} 

這裏StepEnumerable的實施:

public class StepEnumerator<T> : IEnumerator<T> 
{ 
    ... 

    public StepEnumerable(T value, Func<T, T> manipulation) 
    { 
     mEnumerator = new StepEnumerator<T>(value, manipulation); 
    } 

    public static StepEnumerable<T> Create(T value, Func<T, T> manipulation) 
    { 
     return new StepEnumerable<T>(value, manipulation); 
    } 

    ... 
} 

public class StepEnumerator<T> : IEnumerator<T> 
{ 
    public bool MoveNext() 
    { 
     Current = mManipulation(Current); 
     return true; 
    } 
} 

然後,例如,如果您運行下面的代碼:

ParallelFor(3, 16, x => x + 2, Console.WriteLine); 

你會得到下面的輸出(當然,在不同的行):

5,11,7,13,9,15