多线程下载管理器和DataGridView

时间:2017-04-16 07:12:53

标签: c# multithreading datagridview task

我试图同时下载两个文件,不知怎的,我得到一个"索引超出了数组的范围。"

            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。

1 个答案:

答案 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。