2013-04-06 2 views
1

Когда мы используем foreach и Tasks мы должны использовать локальные переменные, как это:Parallel.ForEach против Foreach и задачи в локальной переменной

List<Task> TaskPool = new List<Task>(); 
foreach (TargetType Item in Source) 
{ 
    TargetType localItem = Item; 
    TaskPool.Add(Task.Factory.StartNew(() => DoSomething(localItem))); 
} 
Task.WaitAll(TaskPool.ToArray()); 

Но как Parallel.Foreach, я использую его, как это:

Parallel.ForEach(Source, (TargetType item) => DoSomething(item)); 

Таким образом, нет локальной переменной, как вы видите. Но как работает Parallel.Foreach? Нет необходимости вводить какие-либо локальные переменные? или, если необходимо, как я могу его определить?

UPDATE

Есть ли разница в .NET 4 и .NET 4.5?

+0

Начиная с C# 5, на самом деле локальная переменная не нужна, поскольку переменные цикла семантически находятся внутри цикла. –

+0

@mikez Что значит цикл? вы подразумеваете как «foreach», так и «Parallel.foreach»? Если да? так как насчет .NET 4? – Saeid

+1

В C# 5 локальная переменная не нужна в цикле foreach (я бы сказал, что «Parallel.ForEach» - это вызов метода, а не цикл). В C# 4 это необходимо. Я также хотел бы отметить, что это поведение компилятора, а не поведение во время выполнения. Это «разрыв» с предыдущими версиями компилятора. См. Http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx –

ответ

2

Вы не определите локальные переменные в Parallel.ForEach - item это не более чем формальный параметр - код реализации Parallel.ForEach является тот, который будет обрабатывать переменные, и они являются локальными, захвачено или что-то еще ли.

Нет необходимости определять локальную переменную, связанную с формальным параметром Parallel.ForEach - код вызывающего абонента вашего анонимного делегата обрабатывает переменную и передает ее вашей функции.

Однако в C# 4, возможно, потребуется использовать локальную переменную, если вы захватить другую переменную, то есть:

void DoSomething(ItemType item, OtherType other) { 
} 

void YourFunction(IEnumerable<ItemType> items, IEnumerable<OtherType> others) { 

    foreach (var otherItem in others) { 
     var localOtherItem = otherItem; 
     Parallel.ForEach(items, item => DoSomething(item, localOtherItem)); 
    } 
} 

Вы можете увидеть разницу выше: localOtherItem берется из контекста, в котором анонимный функция определена: это называется замыканием. В то время как элементы в items передаются просто как параметр метода анонимной функции.

Коротко: item в Parallel.ForEach и item в C# foreach две очень разные проблемы.

Смежные вопросы