启动新线程时抛出 IndexOutOfRangeException
当我运行以下代码段时,会引发 IndexOutOfRangeException。看起来抛出异常时 i 是 2。我的理解是,i的值改变后,新线程就启动了。有没有办法让这段代码免受此类问题的影响?
int x[2] = {1, 3};
int numberOfThreads = 2;
for (int i = 0; i < numberOfThreads; i++)
{
new Thread(() =>
{
DoWork(x[i]);
}).Start();
}
When I run the following code piece, a IndexOutOfRangeException is thrown. It appears that i is 2 when the exception is thrown. My understanding is that the new thread is started after the value of i has been changed. Is there a way to make this code safe from this kind of problem?
int x[2] = {1, 3};
int numberOfThreads = 2;
for (int i = 0; i < numberOfThreads; i++)
{
new Thread(() =>
{
DoWork(x[i]);
}).Start();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是 变量
i
被捕获,当线程实际启动时,它是 2。请改用:
Or:
Or:
在每种情况下,lambda 表达式将在循环的每次迭代中捕获一个新变量 - 该变量不会被后续迭代更改。
一般来说,您应该避免在稍后执行的 lambda 表达式中捕获循环变量。请参阅 有关更多详细信息,请参阅 Eric Lippert 关于该主题的博客文章。
从 C# 5 开始,
foreach
循环行为可能会发生变化,以避免出现问题 - 但for
循环等效项仍然是一个问题。The problem is that the variable
i
is being captured, and by the time the thread actually gets to start, it's 2.Use this instead:
Or:
Or:
In each case, the lambda expression will capture a new variable on each iteration of the loop - a variable which won't be changed by subsequent iterations.
In general, you should avoid capturing the loop variable in a lambda expression which will be executed later. See Eric Lippert's blog post on the topic for more details.
As of C# 5, it's likely that the
foreach
loop behaviour will be changed to avoid this being a problem - but thefor
loop equivalent would still be an issue.您正在关闭循环变量,为了获取
i
的当前值,请使用本地副本:You are closing over the loop variable, to get the current value of
i
use a local copy instead: