У меня есть длинный словарь URL-адресов изображений и имя файла, чтобы загрузить и сохранить их как. Я использую очищающий сайт (ScrennScraper.fr), который разрешает это в определенном количестве потоков. У меня есть 7. Я ищу наиболее эффективный / действенный способ сделать это. Мой запрос в основном касался того, как реализовать цикл и многопоточность.
Я пытался использовать Parallel.ForEach
и манипулировать .MaxDegreeOfParallelism
. Это частично работает, но кажется узким местом в 3 потоках. Мой существующий код:
Dim dltime As New Stopwatch
dltime.Start()
Dim testThreadsNumber = 6
Dim opt As System.Threading.Tasks.ParallelOptions = New System.Threading.Tasks.ParallelOptions With {
.MaxDegreeOfParallelism = testThreadsNumber
}
ThreadPool.SetMinThreads(testThreadsNumber, testThreadsNumber)
Parallel.ForEach(downloadList, opt,
Sub(f As KeyValuePair(Of String, String))
Debug.WriteLine(vbCr & "Downloading to: " & f.Key)
DownloadImage(f.Key, f.Value)
End Sub)
dltime.Stop()
Манипулируя testThreadsNumber
, это производит следующее время:
Загрузка с 1 потоков: 21 с: 55 мс
Загрузка с 2 потоков: 13 с: 16 мс
Загрузка с 3 потоков: 12 с: 198 мс
Загрузка с 6 потоков: 12 с: 139 мс
Загрузка с 6 потоков: 12 с: 328 мс
Все условия сбрасываются между запусками.
Я где-то читал, что parallel.foreach
не обязательно использует отдельный поток для каждого процесса. Таким образом, если он использует только 3 потока вместо 6, то это может объяснить узкое место, так как сайт может рассматривать мое приложение как работающее только с 3 потоками? Итак, я включил нижеприведенный код в код до цикла, чтобы попытаться убедиться, что они выполняются в отдельных потоках (не уверен в правильности этого):
ThreadPool.SetMinThreads(testThreadsNumber, testThreadsNumber)
Это не имело никакого значения.
Я также читал, что там, где есть операции ввода-вывода (что будет иметь место в данном случае: загрузка http и сохранение файла), тогда parallel.foreach
меньше указано, чем Task
для этих процессов (https://stackoverflow.com/a/32918094/3472225). Тем не менее, я не имею ни малейшего представления о его прожорливости или о том, как его достичь.
Широкий вопрос такой же, как в названии.
Более конкретные вопросы:
Как я могу сказать или гарантировать, что каждый экземпляр parallel.foreach
работает в отдельном потоке?
Стоит ли вместо этого использовать задачи? Еслитак - как бы я это сделал?
Я могу опубликовать более широкий ссылочный код, если это необходимо (хотя это все довольно стандартные WebClient
вещи).
Спасибо ваванс за любую предложенную помощь.