创建任务时列出索引超出范围异常

sox*_*oxr 15 c# lambda task indexoutofboundsexception indexoutofrangeexception

确切的错误:

指数超出范围.必须是非负数且小于集合的大小.

我已经无数次索引数组和列表.我用过数组循环和列表无数次.数据在那里,它的工作原理.除非我尝试为我的功能创建任务.请注意,我成功地使用foreach循环执行此类功能; 这个新的需要两个参数,所以我不能正确使用foreach循环.至少我认为我不能.

这是错误的代码:

if (addressList != null) {
    textBox1.Text += ("Address List Length: " + addressList.Count + Environment.NewLine);

    for (int i = 0; i < addressList.Count; i++) {
        textBox1.Text += ("Task for " + addressList[i] + ":" + portList[i] + " initiated." + Environment.NewLine);

        Task.Factory.StartNew(() => PingTaskAdapted(addressList[i], portList[i]));
    }                
}
else textBox1.Text = ("No IPs have been added.");
Run Code Online (Sandbox Code Playgroud)

假设addressList[0]是google.com并且portList[0]是80,输出:

Address List Length: 1
Task for google.com:80 initiated.
Run Code Online (Sandbox Code Playgroud)

然后程序中断,Visual Studio告诉我在PingTaskAdapted()中我正在调用一个超出范围的索引,当它只是打印出有问题的索引时,因为它们存在.

而且要明确的是,如果我称之为PingTaskAdapted(addressList[0], pingList[0]);没有问题.

nvo*_*igt 17

任务运行时,您的任务将访问列表.不是你在循环中看到的代码行中的顺序.要确保在闭包中捕获正确的值(并且列表仍然存在且具有相同的值),请在任务之外创建本地副本,以确保在循环运行的时间点捕获值:

var localAddress = addressList[i];
var localPort = portList[i];
Task.Factory.StartNew(() => PingTaskAdapted(localAddress , localPort));
Run Code Online (Sandbox Code Playgroud)


J. *_*een 7

你是访问修改后的闭包的受害者,因为它被简洁地称之为.基本上,既然你正在使用一个任务 - 以及一个代理来启动 - i那么它的价值并不能保证你所期望的那样.但是,如果您复制i到一个局部变量,特定于一次迭代的范围,那么您应该没问题.

for (int i = 0; i < addressList.Count; i++)
{
    textBox1.Text += ("Task for " + addressList[i] + ":" + portList[i] + " initiated." + Environment.NewLine);

    var iCopy = i;
    Task.Factory.StartNew(() => PingTaskAdapted(addressList[iCopy], portList[iCopy]));
}
Run Code Online (Sandbox Code Playgroud)


但是,正如nvoigt这个答案中指出的那样,如果你复制将要使用的值而不是迭代器值,那么在可读性和可维护性方面就更加明确了.


InB*_*een 5

闭包捕获变量,而不是.

将代码更改为以下内容,您将看到问题消失:

for (int i = 0; i < addressList.Count; i++) {
    textBox1.Text += ("Task for " + addressList[i] + ":" + portList[i] + " initiated." + Environment.NewLine);

    var temp = i;
    Task.Factory.StartNew(() => PingTaskAdapted(addressList[temp], portList[temp]));
    }                
Run Code Online (Sandbox Code Playgroud)