代码之家  ›  专栏  ›  技术社区  ›  soxroxr

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

  •  16
  • soxroxr  · 技术社区  · 8 年前

    索引超出范围。必须为非负数且小于集合的大小。

    我有无数次索引数组和列表。我已经无数次使用数组和列表的循环。数据就在那里,它是有效的。除非我尝试为我的函数创建任务。请注意,我为类似的函数成功地使用了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.");
    

    假设 addressList[0] portList[0] 输出:

    Address List Length: 1
    Task for google.com:80 initiated.
    

    说清楚一点,如果我打电话 PingTaskAdapted(addressList[0], pingList[0]); 它可以正常工作。

    3 回复  |  直到 8 年前
        1
  •  18
  •   nvoigt    8 年前

    var localAddress = addressList[i];
    var localPort = portList[i];
    Task.Factory.StartNew(() => PingTaskAdapted(localAddress , localPort));
    
        2
  •  8
  •   J. Steen    8 年前

    您是访问修改的闭包的受害者,正如我们所说的那样。基本上,由于您使用任务和委托来引导,因此 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]));
    }
    


    然而,正如 this answer by nvoigt ,如果复制将要使用的值而不是迭代器值,那么在可读性和可维护性方面就更清楚了。

        3
  •  5
  •   InBetween    8 年前

    变量

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

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