启动新线程时抛出IndexOutOfRangeException [英] IndexOutOfRangeException is thrown when starting a new thread

查看:78
本文介绍了启动新线程时抛出IndexOutOfRangeException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我运行以下代码段时,将抛出IndexOutOfRangeException.当抛出异常时,看来我是2.我的理解是,更改i的值后,将启动新线程.有没有办法使该代码免受此类问题的影响?

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();
}

推荐答案

问题是捕获了变量 i,并且在线程真正开始启动时,它是2

The problem is that the variable i is being captured, and by the time the thread actually gets to start, it's 2.

改为使用此:

for (int i = 0; i < numberOfThreads; i++)
{
    int value = x[i];
    new Thread(() => DoWork(value)).Start();
}

或者:

foreach (int value in x)
{
    int copy = value;
    new Thread(() => DoWork(copy)).Start();
}

或者:

for (int i = 0; i < numberOfThreads; i++)
{
    int copyOfI = i;
    new Thread(() => DoWork(x[copyOfI])).Start();
}

在每种情况下,lambda表达式都会在循环的每次迭代中捕获一个新变量,该变量不会被后续迭代更改.

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.

通常,应避免在lambda表达式中捕获循环变量,该表达式稍后将执行.参见埃里克·利珀特(Eric Lippert)关于该主题的博客文章,以获取更多详细信息.

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.

从C#5开始,很可能会更改foreach循环行为以避免出现问题-但for循环等效项仍然会成为问题.

As of C# 5, it's likely that the foreach loop behaviour will be changed to avoid this being a problem - but the for loop equivalent would still be an issue.

这篇关于启动新线程时抛出IndexOutOfRangeException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆