C# - 在for循环中使用相同的列表大小,索引超出了数组的范围[重复]

Posted

技术标签:

【中文标题】C# - 在for循环中使用相同的列表大小,索引超出了数组的范围[重复]【英文标题】:C# - Index was outside the bounds of the array using same list sizes in for loop [duplicate] 【发布时间】:2017-10-26 07:41:25 【问题描述】:

我正在.NET 中创建一个文件下载器,它使用异步任务从服务器下载一组文件。但是,即使我创建了 Task[] 并返回了相同长度的 string[]

这是我的方法:

    public static string[] DownloadList(string[] urlArray, string[] toPathArray, string login = "", string pass = "", bool getExt = false)
    
        Console.WriteLine("DownloadList(0, 1, 2, 3, 4)", urlArray, toPathArray, login, pass, getExt);
        try 
            returnedArray = new string[urlArray.Length];
            Task[] taskArray = new Task[urlArray.Length];
            for (int i = 0; i < urlArray.Length; i++)
            
                Thread.Sleep(1000);
                Console.WriteLine("i = 0", i);
                Task task = new Task(() =>  returnedArray[i] = Download(urlArray[i], toPathArray[i], login, pass, getExt, true); );
                task.Start();
                taskArray[i] = task;
            
            Task.WaitAll(taskArray);
            Thread.Sleep(1000);
            Console.WriteLine();
            Console.WriteLine("Done! Press Enter to close.");
            Console.ReadLine();
            return returnedArray;
        
        catch(Exception e)
        
            Console.WriteLine();
            Console.WriteLine(e.Message);
            Console.ReadLine();
            return null;
        
    

还有例外:

指向这条线:

我知道我错过了一些愚蠢的事情,但我正在努力解决这个问题。提前感谢您的帮助!

【问题讨论】:

在最后一次迭代中,当 i 为 9 时,您运行任务 task.Start();,并且很有可能在迭代结束后工作,i++ 工作,在这种情况下,您的 i 将变为 @ 987654332@ 制作i 的本地副本以在 lambda 中使用。直到循环完成后,您的 lambda 才会执行,此时 i = 10 - 对于 lambda 的所有十个副本。 @jdweng i &lt; a.Length 是正确的。如果a.Length == 10i 永远不会超过 9。你在想&lt;= @S.Petrosov 它很可能出现在 all 迭代中。循环将很快完成......将任务调度到 ThreadPool(或其他任何地方)可能需要更长的时间。 那些Thread.Sleep 电话让我很痒。 【参考方案1】:

@Backs 的回答是正确的。有趣的是,在.Net 的最新版本中,如果您使用foreach,那么循环变量将被关闭。所以,你可以:

foreach(var i in Enumerable.Range(0, urlArray.Length))

    ... new Task(() =>  returnedArray[i] = ...

无需复制。

【讨论】:

【参考方案2】:

看起来您将数组过冲了 1,因为您计算循环中数组的长度,即 10,而数组从 0 变为 9。

 for (int i = 0; i < urlArray.Length; i++)

应该是

 for (int i = 0; i < urlArray.Length - 1; i++)

【讨论】:

【参考方案3】:

看起来像Access to Modified Closure 问题。 复制i 到局部变量:

for (int i = 0; i < urlArray.Length; i++)

    int index = i;
    Thread.Sleep(1000);
    Console.WriteLine("i = 0", index );
    Task task = new Task(() =>  returnedArray[index] = Download(urlArray[index], toPathArray[index], login, pass, getExt, true); );
    task.Start();
    taskArray[index] = task;

【讨论】:

谢谢。就是这样。我只是在索引中添加了一个本地 int 并在循环中使用它

以上是关于C# - 在for循环中使用相同的列表大小,索引超出了数组的范围[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在并行 for 循环 C# 中定义堆栈大小

具有相同索引的 for 循环的性能

简单python for循环上的列表索引超出范围错误

Python 列表list详解(超详细)

C#以int数组为索引过滤for循环的更快方法?

C#集合