【问题标题】:C# - Index was outside the bounds of the array using same list sizes in for loop [duplicate]C# - 在for循环中使用相同的列表大小,索引超出了数组的范围[重复]
【发布时间】: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 电话让我很痒。

标签: c# .net arrays asynchronous task


【解决方案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 并在循环中使用它
      猜你喜欢
      • 2017-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-17
      • 1970-01-01
      • 2019-01-07
      • 2020-07-23
      • 2020-11-01
      相关资源
      最近更新 更多