#c# #multithreading #visual-studio #thread-safety
#c# #многопоточность #visual-studio #безопасность потоков
Вопрос:
Я хочу запустить класс с другим значением в списке потоков. вот так :
int index = 0;
foreach (TreeNode nd in tvew.Nodes[0].Nodes)
{
threadping[index] = new Thread(delegate()
{ this.Invoke(new DelegateClientState(InvokeCheckNetworkState), new object[] {nd}); });
threadping[index].Name = nd.Name;
threadping[index].IsBackground = true;
threadping[index].Start();
index ;
}
но когда я отлаживаю код, я вижу, что параметр класса — это просто последнее значение.
я имею в виду, что когда я просматриваю класс thread, я вижу, что каждый раз, когда этот класс запускается, значение входного параметра является последним значением для последнего потока.
Кто-нибудь может сказать мне, ПОЧЕМУ?
Комментарии:
1. Можете ли вы показать код, в котором вы инициализировали коллекцию threadPing. И что такое «параметр класса» или какой класс потока вы отлаживаете?
Ответ №1:
Это потому, что переменная nd фиксируется в замыкании. При запуске потоков все они ссылаются на один и тот же экземпляр TreeNode, а именно на последний, которому был назначен nd
. Для исправления используйте отдельную переменную, которая не изменяется в пределах области видимости:
foreach (TreeNode nd in tvew.Nodes[0].Nodes)
{
var current = nd;
threadping[index] = new Thread(delegate()
{ this.Invoke(new DelegateClientState(InvokeCheckNetworkState), new object[] {current}); });
Если мы получаем compiler-technical, это происходит потому, что компилятор генерирует анонимный класс, содержащий вашу переменную цикла, чтобы сделать его доступным для делегата потока. Это ожидаемое поведение, хотя, возможно, немного нелогичное, когда вы сталкиваетесь с ним в первый раз.
Для более подробного объяснения замыканий и захвата переменных, смотрите раздел «Захваченные переменные» здесь (нижняя часть) в статье Джона Скита или в этой статье Эрика Липперта. Это обычно известно как ошибка «доступ к измененному закрытию». Если вы выполните поиск по термину в StackOverflow или Google, вы получите множество обращений, объясняющих это.
Комментарии:
1. спасибо, это работает. другой вопрос: почему мои потоки не работают одновременно? я указываю точку останова в первой строке «InvokeCheckNetworkState», которая возникает при завершении первого цикла. это похоже на то, что потоки ожидают завершения предыдущего потока. я имею в виду, что ты не работаешь одновременно. Что мне делать?