This question already has an answer here:
这个问题在这里已有答案:
- Thread parameters being changed 2 answers
线程参数被更改2个答案
I am creating a file downloader in .NET which downloads an array of files from a server using Asynchronous tasks. However, even though I create the Task[]
and returned string[]
with the same length.
我在.NET中创建一个文件下载器,它使用异步任务从服务器下载文件数组。但是,即使我创建了Task []并返回了具有相同长度的string []。
Here is my method:
这是我的方法:
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;
}
}
and the exception:
和例外:
which points to this line:
这指向这一行:
I know it will be something daft that I missed, but I'm rattling my brain trying to figure it out. Thanks for the help in advance!
我知道这会让我错过一些愚蠢的东西,但是我正在喋喋不休地试图解决它。我在这里先向您的帮助表示感谢!
3 个解决方案
#1
8
It looks like Access to Modified Closure problem. Copy i
to local variable:
它看起来像访问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;
}
#2
2
@Backs's answer is correct. Interestingly, in recent versions of .Net, if you use foreach
, then the loop variable is closed over. So, you could:
@Backs的回答是正确的。有趣的是,在.Net的最新版本中,如果使用foreach,则循环变量将被关闭。所以,你可以:
foreach(var i in Enumerable.Range(0, urlArray.Length))
{
... new Task(() => { returnedArray[i] = ...
}
without needing to take a copy.
无需复制。
#3
-1
Looks like you are overshootinhg the array by one, because you count the length of the array in the cycle, and that's 10, while the array goes from 0 to 9.
看起来你的数字超过了一个,因为你计算周期中数组的长度,那是10,而数组从0到9。
for (int i = 0; i < urlArray.Length; i++)
Should be
for (int i = 0; i < urlArray.Length - 1; i++)
#1
8
It looks like Access to Modified Closure problem. Copy i
to local variable:
它看起来像访问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;
}
#2
2
@Backs's answer is correct. Interestingly, in recent versions of .Net, if you use foreach
, then the loop variable is closed over. So, you could:
@Backs的回答是正确的。有趣的是,在.Net的最新版本中,如果使用foreach,则循环变量将被关闭。所以,你可以:
foreach(var i in Enumerable.Range(0, urlArray.Length))
{
... new Task(() => { returnedArray[i] = ...
}
without needing to take a copy.
无需复制。
#3
-1
Looks like you are overshootinhg the array by one, because you count the length of the array in the cycle, and that's 10, while the array goes from 0 to 9.
看起来你的数字超过了一个,因为你计算周期中数组的长度,那是10,而数组从0到9。
for (int i = 0; i < urlArray.Length; i++)
Should be
for (int i = 0; i < urlArray.Length - 1; i++)