Обработка загрузки нескольких десятков тысяч файлов C#

Я делаю небольшое программное обеспечение, которое загружает несколько десятков тысяч файлов. На данный момент это вообще не эффективно, потому что я скачиваю каждый файл один раз за раз, и поэтому он очень медленный, и много файлов меньше, чем 100ko.

Есть идеи улучшить скорость загрузки?

    /*******************************
        Worker work
    /********************************/
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        listCount = _downloadList.Count;
        // no GUI method !
        while (TotalDownloadFile < _downloadList.Count)
        {
            // handle closing form during download
            if (_worker.CancellationPending)
            {
                _mainView = null;
                _wc.CancelAsync();
                e.Cancel = true;
            }
            else if (!DownloadInProgress && TotalDownloadFile < listCount)
            {
                _lv = new launcherVersion(_downloadList[TotalDownloadFile]);
                var fileToDownloadPath = Info.getDownloadUrl() + _lv.Path;
                var saveFileToPath = Path.GetFullPath("./") + _lv.Path;
                if (Tools.IsFileExist(saveFileToPath))
                    File.Delete(saveFileToPath); // remove file if extist
                else
                    // create directory where the file will be created (use api this don't do anything on existing directory)
                    Directory.CreateDirectory(Path.GetDirectoryName(saveFileToPath));
                StartDownload(fileToDownloadPath, saveFileToPath);
                UpdateRemaingFile();
                _currentFile = TotalDownloadFile;
            }
        }
    }

Начать загрузку

    /*******************************
        start the download of files
    /********************************/
    public void StartDownload(string fileToDownloadLink, string pathToSaveFile)
    {
        try
        {
            using (_wc = new WebClient())
            {
                _wc.DownloadProgressChanged += client_DownloadProgressChanged;
                _wc.DownloadFileCompleted += client_DownloadFileCompleted;
                _wc.DownloadFileAsync(new Uri(fileToDownloadLink), pathToSaveFile);
                DownloadInProgress = true;
            }
        }
        catch (WebException e)
        {
            MessageBox.Show(fileToDownloadLink);
            MessageBox.Show(e.ToString());
            _worker.CancelAsync();
            Application.Exit();
        }
    }

1 ответ

Расширяя мой комментарий. Вы можете потенциально использовать многопоточность и параллелизм для одновременной загрузки целых пакетов. Однако вам придется приложить некоторые усилия, чтобы убедиться, что каждый поток завершается успешно, и чтобы файлы не загружались дважды. Вы должны были бы защитить свои централизованные списки, используя что-то вроде блокировки.

Я бы лично реализовал 3 отдельных списка: ReadyToDownload, DownloadInProgress, а также DownloadComplete,

ReadyToDownload будет содержать все объекты, которые должны быть загружены. DownloadInProgress будет содержать как загружаемый элемент, так и задачу, обрабатывающую загрузку. DownloadComplete будет содержать все объекты, которые были загружены и ссылаются на задачу, которая выполнила загрузку.

Каждая задача будет гипотетически работать лучше как экземпляр пользовательского объекта. Этот объект будет ссылаться на каждый из списков, и он будет обрабатывать обновление списков, когда он будет работать, либо завершится, либо завершится неудачно. В случае сбоя вы можете либо добавить четвертый список для размещения неисправных элементов, либо повторно вставить их в ReadyToDownload список.

Другие вопросы по тегам