У меня есть код, запускающий процедуру загрузки данных для более чем 2000 компаний. Я изменил процедуру загрузки на 300-секундное ожидание, чтобы не усложнять этот пример. Ниже приведена процедура для одной компании, которой звонящий несколько раз вызывает.
Public Async Function DoJob(ByVal company As Company) As Task(Of Boolean)
Console.WriteLine(String.Format("Started:{0}", company.CompanySymbol))
For i As Long = 1 To 300
Await Task.Delay(1000).ConfigureAwait(False)
Next
Console.WriteLine(String.Format("Ended:{0}", company.CompanySymbol))
Return True
End Function
От звонящего использую:
Dim downloadTasksQuery As IEnumerable(Of Task(Of Boolean)) =
From company In companies Select DoJob(company)
'***Use ToList to execute the query And start the download tasks.
Dim downloadTasks As IEnumerable(Of Task(Of Boolean)) = downloadTasksQuery.ToList()
Await Task.WhenAll(downloadTasks)
Что это делает, так это то, что он параллельно запускает все задачи, и задачи ставятся в очередь, пока не попадут в Интернет и не получат ответ. Из-за большого количества задач время ожидания многих задач истекает, потому что они не могут получить ответ за это время, поскольку количество задач, ожидающих такого ответа в любой момент времени, огромно. (пожалуйста, помните, что я удалил фактический код загрузки, чтобы все было просто, и заменил его длительной задачей, которая просто ждет 300 секунд в методе DoJob выше).
Я хочу ограничить количество запускаемых задач. Скажем, 50. Это будет означать, что в любой момент времени будут активны только 50 задач, остальные будут ждать завершения задач из группы из 50, а затем будут помещены в очередь по мере завершения задачи.
Я пробовал это:
Dim options As New ParallelOptions()
options.MaxDegreeOfParallelism = 100
Parallel.ForEach(companies, options, Sub(company)
' logic
DoJob(company)
End Sub)
Но похоже, что это запускает все задачи за один раз, а не сначала 100, а затем ждет (распечатки из DoJob
приходят для всех 2000+ элементов, а затем задачи завершаются).
Такая же проблема и здесь:
Dim listOfActions = New List(Of Action)()
For Each company In companies
' Note that we create the Action here, but do not start it.
listOfActions.Add(Function() DoJob(company))
Next
Dim options As New ParallelOptions()
options.MaxDegreeOfParallelism = 100
Parallel.Invoke(options, listOfActions.ToArray())
Я пробовал пример @ClearLogics в Как чтобы ограничить максимальное количество параллельных задач в C #
Он также показывает такое же поведение. Все задачи сразу запускаются.
Как мне обойти это - просто нужно запустить 100 задач и подождать, а затем продолжать стоять в очереди, чтобы в любой момент у меня не было более 100 задач.