Параллельная обработка загрузок http на определенное количество потоков - PullRequest
0 голосов
/ 06 октября 2019

У меня есть длинный словарь 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). Тем не менее, я не имею ни малейшего представления о его прожорливости или о том, как его достичь.

Широкий вопрос такой же, как в названии.

Более конкретные вопросы:

  1. Как я могу сказать или гарантировать, что каждый экземпляр parallel.foreach работает в отдельном потоке?

  2. Стоит ли вместо этого использовать задачи? Еслитак - как бы я это сделал?

Я могу опубликовать более широкий ссылочный код, если это необходимо (хотя это все довольно стандартные WebClient вещи).

Спасибо ваванс за любую предложенную помощь.

...