Захваченные переменные в ParameterizedThreadStart
У меня есть следующий код, который создает 10 потоков, которые в свою очередь записывают сообщения на консоль:
for (int i = 0; i < 10; i++)
{
{
Thread thread = new Thread((threadNumber) =>
{
for (int j = 0; j < 10; j++)
{
Thread.Sleep(200);
Console.WriteLine(string.Format("Thread: {0}, Line: {1}", threadNumber, j));
}
});
thread.Start(i);
}
}
Я понимаю, что ParameterizedThreadStart
принимает объект, для которого копия ссылки отправляется в поток. Если это так, поскольку я не сделал локальную копию i
в каждом цикле все новые потоки будут указывать на одну и ту же ячейку памяти, что означает, что определенные номера потоков могут быть "пропущены". Запустив это, хотя (и даже против большего числа потоков / времени ожидания) каждое значение i
имеет свою нить. Кто-нибудь может объяснить почему?
1 ответ
Вы не применили ничего отложенного или "захваченного" в смысле создания анонимной функции, которая бы переносила i
,
Лямбда-функция здесь не ссылается i
в любом месте, и его состояние полностью усвоено / содержится, поэтому здесь нет проблем:
(threadNumber) =>
{
for (int j = 0; j < 10; j++)
{
Thread.Sleep(200);
Console.WriteLine(string.Format("Thread: {0}, Line: {1}", threadNumber, j));
}
});
Start
позвоните сюда:
thread.Start(i);
Пропуска i
по значению (т.е. копирует свое значение), потому что это "тип значения", и он не фиксируется ни в какой анонимной функции. В этом смысле он передается как любой нормальный struct
было бы к любому нормальному методу (потому что это именно то, что происходит).
Если вместо этого вы написали свою лямбду как это, используя i
вместо вашего threadNumber
:
{
for (int j = 0; j < 10; j++)
{
Thread.Sleep(200);
Console.WriteLine(string.Format("Thread: {0}, Line: {1}", i, j));
}
});
Тогда у тебя будут проблемы. В этом случае i
относится к исходному расположению переменной и будет оцениваться всякий раз, когда выполняется поток. Это означает, что это может быть текущее значение i
когда он был создан (маловероятно только из-за времени обработки), или значение, установленное позже в for
цикл или последнее возможное значение 10
и вполне возможно, что число пропущено или разделено между итерациями.