WebClient.Загрузка файла в фоновом режиме неприемлема с точки зрения производительности

#.net #backgroundworker #downloadfile

#.net #webclient #backgroundworker

Вопрос:

У меня есть приложение WinForms, которому необходимо загружать много (десятки тысяч) файлов довольно большого размера (несколько МБ) в день. Я написал простой тест, используя следующий код:

 using (var wc = new System.Net.WebClient())
{
    foreach (string url in UrlsToDownload())
    {
        string targetPath = SafeFilePathOf(url);
        wc.DownloadFile(url, targetPath);
    }
}
  

На целевой машине установлено соединение со скоростью 1 Гб / с, но тестирование показывает постоянную загрузку около 1 МБ / с. Это меньше, чем я ожидал, но исходные серверы могут иметь более медленные соединения. Загрузка на целый день потребует нескольких часов подключения, что приемлемо. Загрузка сети довольно постоянна и составляет около 1%:

Загрузка файла в потоке пользовательского интерфейса

Однако мне нужно выполнять загрузки в фоновом потоке и поддерживать отмену и прогресс загрузки. The .Сеть System.ComponentModel.BackgroundWorker , похоже, предназначена для этого, поэтому я помещаю точно такой же код в BackgroundWorker экземпляр и вызываю RunWorkerAsync : Загрузка файла в BackgroundWorker

Производительность загрузки падает примерно до 0,05 МБ / с. Для выполнения дневной работы потребуется около недели; это не сработает.

Почему BackgroundWorker производительность такая плохая? Ни процессор, ни сеть не перегружены. Приложение не заблокировано, я просто переместил код загрузки из потока пользовательского интерфейса в BackgroundWorker . Вызов backgroundWorker.Priority = ThreadPriority.AboveNormal не имеет эффекта.

Комментарии:

1. Нет никакой разницы в производительности сети, будь то в любом потоке, я думаю, что это другой код производительности отчетов и т.д., Который может замедлять поток. Можете ли вы опубликовать свой полный исходный код темы BG?

2. Загрузка процессора выросла с 1% до 9%. Сначала решите это.

3. Я все равно рекомендую вам использовать асинхронную версию — DownloadFileAsync .

Ответ №1:

Увеличьте лимит подключения к WebClient:

 internal class CustomWebClient : WebClient
{
    public CustomWebClient()
    {
    }

    protected override WebRequest GetWebRequest(Uri uri)
    {
        HttpWebRequest w = (HttpWebRequest)base.GetWebRequest(uri);

        w.ServicePoint.ConnectionLimit = 100;
        return w;
    }
}
  

Ответ №2:

Сетевая активность выполняется одинаково, будь то фоновый поток или поток пользовательского интерфейса. Проблема может заключаться в любом другом коде отчета о ходе выполнения или регистрации активности и т.д. Это может заблокировать поток.

Комментарии:

1. И у вас, и у Ханса была правильная идея; это не BackgroundWorker, это был мой регистратор. В тесте потока пользовательского интерфейса был пустой файл журнала, поток BackgroundWorker пытался проанализировать файл журнала размером в несколько МБ после каждой загрузки. Тьфу!