1

When we use foreach and Tasks we need to use local variables like this:

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());

But how about Parallel.Foreach, I use it like this:

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

So there is not any Local Variable as you see. But how does Parallel.Foreach work? Is there no need to introduce any local variables? or if needed, how can I define it?

UPDATE

Is there any difference in .NET 4 and .NET 4.5?

Saeid
  • 13,224
  • 32
  • 107
  • 173
  • As of C# 5, actually the local variable is unnecessary as loop variables are semantically inside the loop. – Mike Zboray Apr 06 '13 at 05:52
  • @mikez What do you mean of loop? you mean both `foreach` and `Parallel.foreach`? if yes? so how about .NET 4? – Saeid Apr 06 '13 at 06:01
  • 1
    In C# 5, the local variable is unnecessary in the `foreach` loop (I'd say `Parallel.ForEach` is a method call not a loop). In C# 4 it is necessary. I would also note this is compiler behavior, not runtime behavior. This is a "breaking" change from previous compiler versions. See http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx – Mike Zboray Apr 06 '13 at 06:15
  • Please inform me what is so heavy wrong [in my answer](http://stackoverflow.com/a/15850049/200449) that it was so hevy downvoted. I am really curious – Gennady Vanin Геннадий Ванин Apr 06 '13 at 12:01
  • @Gennady Vanin -- Novosibirsk I don't know why the others down voted, but in my case: First: .Net 4.5 tagged because I use .Net 4.5 Second: both versions are correct none of them is not wrong, Third: your description is so ambiguous and the code you pasted why use Parallel.foreach and Task and Taskpool together, what advantages you followed? and also in your Update: there not the same result. thanks – Saeid Apr 06 '13 at 12:55
  • @Saeid, I explained your misunderstanding of the local variable "So there is not any Local Variable" in `ForLoop()` and there is one in `foreach()` loop body. It is programmer who either introduce a local var or not. There is no difference in this respect between `ForLoop()` or `foreach()`. It is you who has provided the code code with local var `localItem`! You could have done the same for both cases, or avoided it in both. But you've chosen to mix them having made your question unanswerable! – Gennady Vanin Геннадий Ванин Apr 06 '13 at 14:06
  • All your other questions and doubts are too many for one topic and were many times answered all over the internet. Anyway, feel free to ask them separately having formulated them less ambiguous and provocative ways! – Gennady Vanin Геннадий Ванин Apr 06 '13 at 14:10

1 Answers1

2

You do not define any local variable in Parallel.ForEach - item is nothing more than a formal parameter - the implementation code of Parallel.ForEach is the one that will have to handle variables, and whether they are local, captured or something else.

There is no need to define a local variable related to the formal parameter Parallel.ForEach - the caller code of your anonymous delegate will handle the variable and pass it to your function.

However in C#4, you might need to use a local variable if you capture another variable, that is:

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));
    }
}

You can see the difference above: localOtherItem is taken from the context where the anonymous function is defined: that is called a closure. Whereas the items in items are passed simply as a method parameter to the anonymous function.

In short: the item in Parallel.ForEach and the item in C# foreach are two very different problems.

Jean Hominal
  • 16,518
  • 5
  • 56
  • 90