This is the classic loop-variable closure problem in C#.
Your loop does stop at a million.
After it stops at a million, you make some large number of calls to WriteHelloAsync(i)
.
You're passing i
to all of them. That lambda you're passing to Task.Run()
isn't creating a new copy of i
that holds the value i
had at the time of that particular call to Task.Run()
. They all have the same i
, whose value keeps changing until the loop ends.
On my machine here, the first number I see is well into six digits, meaning that's the value of i
the first time a task actually gets around to calling WriteHelloAsync()
. Very shortly thereafter, it starts doing the million-million-million thing you see.
Try this:
static void Main(string[] args)
{
for (int i = 0; i < 1000 * 1000; i++)
{
// The scope of j is limited to the loop block.
// For each new iteration, there is a new j.
var j = i;
Task.Run(() => WriteHelloAsync(j));
}
Console.ReadLine();
}
@Gigi points out that this will also work with a foreach
rather than for
:
foreach (var i in Enumerable.Range(0, 1000 * 1000))
{
Task.Run(() => WriteHelloAsync(i));
}