Захваченные переменные в 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и вполне возможно, что число пропущено или разделено между итерациями.

Другие вопросы по тегам