我试图同时下载两个文件,不知怎的,我得到一个"索引超出了数组的范围。"
var downloadthread1 = new FileDownload();
var downloadthread2 = new FileDownload();
downloadthread1.DownloadProgressChanged += DownloadProgressChanged;
downloadthread1.DownloadCompleted += DownloadCompleted;
downloadthread2.DownloadProgressChanged += DownloadProgressChanged;
downloadthread2.DownloadCompleted += DownloadCompleted;
Task.Factory.StartNew(() => downloadthread1.Start(downloadDataGridView.Rows[0].Cells[1].Value.ToString(), 0));
Task.Factory.StartNew(() => downloadthread2.Start(downloadDataGridView.Rows[1].Cells[1].Value.ToString(), 1));
Task.WaitAll();
这部分有效,但当我在循环中执行此操作时似乎不起作用:
FileDownload[] fileDownloads = new FileDownload[2];
fileDownloads[0] = new FileDownload();
fileDownloads[1] = new FileDownload();
for (int i = 0; i < 2; i++)
{
fileDownloads[i].DownloadProgressChanged += DownloadProgressChanged;
fileDownloads[i].DownloadCompleted += DownloadCompleted;
fileDownloads[i].m_UrlQueue.Enqueue(m_Downloader.m_UrlQueue.Dequeue());
string downloadPath = downloadDataGridView.Rows[i].Cells[1].Value.ToString();
Task.Factory.StartNew(() => fileDownloads[i].Start(downloadPath, i));
}
正如ReSharper所说,这可能是一个叫做“#34;访问修改后的封闭”的问题,除了我不改变i索引这一事实似乎也是问题。
我必须在线程中使用索引才能更新DownloadProgressChanged和Completed中的DataGridView。
答案 0 :(得分:1)
Resharpes建议您不要在for循环中使用变量 i 。您必须创建新变量并为其指定 i ,然后在循环内使用新变量。
一些基本代码来演示这个概念:
for (int i = 0; i < 10; i++)
{
new Thread(() => Console.Write(i)).Start();
}
这不可能打印0123456789因为当你一次运行多个线程并且他们使用全局变量时,thread5有可能比thread6晚访问 i 。
要解决这个问题,我们必须这样做:
for (int i = 0; i < 10; i++)
{
int temp = i;
new Thread(() => Console.Write(temp)).Start();
}
因为 temp 不是全局变量,而是每个线程的本地变量,所以不会有任何问题,输出将始终是0123456789。