#.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%:
System.ComponentModel.BackgroundWorker
, похоже, предназначена для этого, поэтому я помещаю точно такой же код в BackgroundWorker
экземпляр и вызываю RunWorkerAsync
: 
Производительность загрузки падает примерно до 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 пытался проанализировать файл журнала размером в несколько МБ после каждой загрузки. Тьфу!