在c#中,当线程在循环中创建时,将值传递给线程启动方法
本文关键字:线程 启动 方法 值传 创建 循环 | 更新日期: 2023-09-27 18:12:00
我在循环中创建线程,我需要在线程启动方法中传递循环计数器(就像线程创建时一样)。
for (int i = 0; i < ListSize; i++)
{
thread = new Thread(() =>
Helper.GetEndToEndRequestProcessTime(EmailList[i], reqResultData, i, ListSize));
workerThreads.Add(thread);
thread.Start();
}
在上面的例子中,i
是作为GetEndToEndRequestProcessTime()
参数的变量I。但问题是,当实际线程是i
的起始值正在变化,我在GetEndToEndRequestProcessTime()
得到错误的结果。
如何确保在线程启动时传递给GetEndToEndRequestProcessTime()
的值与创建线程时提供的值相同
一个经典的闭包和捕获变量问题,每个新人都必须问。
for (int i = 0; i < ListSize; i++)
{
var j = i;
thread = new Thread(() => Helper.GetEndToEndRequestProcessTime(EmailList[j], reqResultData, j, ListSize));
workerThreads.Add(thread);
thread.Start();
}
更多信息:http://csharpindepth.com/articles/chapter5/closures.aspx
如前所述,这里的问题是闭包问题。
这意味着因为你只为i
分配一个变量,当你通过在new Thread(() => ...)
中引用它来捕获它时,你实际上是在复制变量的地址。因此,当变量在下一个循环中增加时,在第一个thread
中进行的操作将获得更新的值,因为它都指向i
的单个值。
解决这个问题的方法是将该变量复制到一个新的变量中,然后捕获新变量。通过在循环中声明它,每次迭代都会生成一个新的,因为循环的内部作用域在迭代之间是不共享的。
请注意,类似的问题也适用于。net 4.0及更早版本的foreach
循环中的capture变量,但在4.5及以上版本中已修复。
我如何确保在线程启动值的时候传递给GetEndToEndRequestProcessTime()时提供的相同线程被创建了?
答案:通过创建一个本地副本来记住i
的值,当执行命令给这个任务/线程时,然后传递这个本地副本。
确切问题:当你启动你的任务/线程时,i
的值已经改变,因此你的执行是意外的