1

I've read Task.Run with Parameter(s)? Follow the ways suggested in some answers, I'll have the following issue.

var tasks = new List<Task>();

for (int i = 0; i < 10; i++)
    tasks.Add(Task.Run(() => Console.WriteLine(i)));
Task.WaitAll(tasks.ToArray());

Normally I would expected it passes the values of i from 0 to 9 to the lambda in the Task.Run() each time. Turned out the actual values passed in really depend, but most likely it just creates all the 10 tasks and then runs them, so what prints out is just all 10s like: 10, 10, 10, 10, 10, 10, 10, 10, 10, 10. Or sometimes it's: 3, 3, 3, 10, 10, 10, 10, 10, 10, 10.

So how can I solve this nicely? Or in this situation, have to use Task.Factory.StartNew()?

cateyes
  • 5,208
  • 2
  • 24
  • 31

1 Answers1

0

Try to make a copy of your counter inside the loop, as in this answer. Such a moments with the closures are hard to explain and understand. Try reading this.

NaivE
  • 95
  • 5
  • The example you refer to with the closure has a problem. The example shown in the article that allegedly should return 120, 120, 120 does in fact return 100, 110, 120 (I tried it in .Net Framework and Core). In other words the initial code is returning exactly what is expected making the discussion following pointless. – Paul Sinnema May 10 '21 at 13:10
  • 1
    Well, looking at "update" section at the top of the article, you are right. It states that since C#5 the foreach variable " will be logically inside the loop, and therefore closures will close over a fresh copy of the variable each time", but the "for" loop will not be changed. But, nevertheless, the explanation of closures after the example is worth reading and understanding in my opinion. – NaivE May 11 '21 at 12:53