启动Thread线程时如何给方法传参?for循环内传参异常如何解决
问题原因
这是C#语言中闭包变量捕获的典型问题:
- for循环的迭代变量
k是在循环外部的作用域声明的,整个循环过程中只会存在同一个k实例 - 你传入Thread的lambda表达式捕获的是变量
k本身,而非循环执行到当前步骤时k的瞬时值 - 线程启动是异步操作,当线程实际执行lambda调用
Method2时,for循环已经执行完毕,此时k的值已经是循环结束的最终值2,因此所有线程拿到的都是list[2]
解决方法
以下三种方案都可以解决该问题:
方案1:循环内创建局部临时变量拷贝迭代值
每次循环创建一个仅当前迭代可见的局部变量,拷贝当前k的值,让lambda捕获这个独立的局部变量,避免所有lambda共享同一个迭代变量:
for (int k = 0; k < 3; k++) { int currentK = k; // 每次迭代生成独立的局部变量 new Thread(() => Method2(list[currentK])).Start(); }
方案2:使用Thread.Start的参数重载直接传参
Thread类的Start方法支持直接传入参数,参数会在调用Start时就完成值拷贝,不会受后续循环影响:
for (int k = 0; k < 3; k++) { new Thread(param => Method2((string)param)).Start(list[k]); }
方案3:改用foreach遍历集合
C# 5及更高版本中,foreach循环的迭代变量是每次迭代单独生成的,天然避免了变量共享问题,写法更简洁:
// 取前3个元素遍历,和原逻辑等价 foreach (var sym in list.Take(3)) { new Thread(() => Method2(sym)).Start(); }
内容的提问来源于stack exchange,提问作者Blue Turkey
相关产品推荐
相关产品推荐

