Лямбда запоминает только что ей нужно использовать переменную i и не запоминает её значение. Потоки успевают вывести i когда цикл уже закончился и i на тот момент стала 3. Прочитай статью про замыкания в c#
Task[] tasks = new Task[3];
for (var i = 0; i < tasks.Length; i++)
{
var i1 = i;
tasks[i] = new Task(() =>
{
Thread.Sleep(1000); // эмуляция долгой работы
Console.WriteLine($"Task{i1} finished");
});
tasks[i].Start(); // запускаем задачу
}
Console.WriteLine("Завершение метода Main");
скопируй переменную цикла в локальную переменную внутри цикла
Task[] tasks = new Task[3];
for(var i = 0; i < tasks.Length; i++)
{
tasks[i] = new Task(() =>
{
Thread.Sleep(1000); // эмуляция долгой работы
Console.WriteLine($"Task{i} finished");
});
tasks[i].Start(); // запускаем задачу
}
Console.WriteLine("Завершение метода Main");
Task.WaitAll(tasks); // ожидаем завершения всех задач
и в итоге вместо ожидаемых поочередно нумерованных предложений получил это
Завершение метода Main
Task3 finished
Task3 finished
Task3 finished
В чем причина и откуда там вообще взялась 3 ?