限制任务数

问题描述:

我有一个代码可以为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) 

这里做的事情是在平行火灾所有的任务和任务得以排队,直到它到达互联网和具有回一个响应。由于任务数量很大,很多任务都会超时,因为在任何时间点等待此类响应的任务数量巨大,因此他们无法在此时间内获得响应。 (请记住,我已经删除了实际的下载代码以使事情变得简单,并由长时间运行的任务代替,这些任务仅在上面的DoJob方法中等待300秒)。

我想要做的是限制了可以发射任务的数量。说,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例如How to limit the Maximum number of parallel tasks in c#

它也呈现出相同的行为。所有任务立即被解雇。

如何解决这个问题 - 只需要火100个任务等待随后保持在任何时候排队,这样,我没有超过100个任务。

+0

[限制通过并行任务库运行的活动任务数量的最佳方法]的可能重复(https://*.com/questions/11138927/best-way-to-limit-the-number-of-主动任务运行,通过最并行任务天秤座) – cassandrad

您对MaxDegreeOfParallelism的预测不正确,请参阅this的文章,这就是为什么您可以看到同时启动2000个线程的原因。当Await Task.Delay(1000).ConfigureAwait(False)被执行时,线程被认为是空闲的并且可以开始下一个任务。

我想要做的是限制可以触发的任务的数量。

你必须自己去实现它。你可以采取两种方法:

  1. 实现自定义TaskSchedullerthis文章。
  2. 控制较高级别创建的任务的数量,例如,使用信号量来控制并发任务。示例,您可以找到here

如果你会选择第二个选项,我警告你,这只是一个信号量工作的例子。我的意思是,代码不适用于生产。