Asynchronous 限制任务数量

Asynchronous 限制任务数量,asynchronous,async-await,task,task-parallel-library,taskscheduler,Asynchronous,Async Await,Task,Task Parallel Library,Taskscheduler,我有一个为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 30

我有一个为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) 
它所做的是并行触发所有任务,任务排队,直到它到达internet并得到响应。由于任务的数量很多,很多任务都超时了,因为它们无法在时间内得到响应,因为在任何时间点等待此类响应的任务数量都是巨大的。(请记住,我已经删除了下载的实际代码,以保持简单,并用上面的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

它也表现出同样的行为。所有任务都会立即被触发


我该如何解决这个问题?只需启动100个任务,然后继续排队等待,这样在任何时候,我的任务都不会超过100个。

您对
MaxDegreeOfParallelism
的期望是不正确的,请看这篇文章,它解释了为什么您可以看到同时启动2000个线程。当执行
wait Task.Delay(1000).configurewait(False)
时,假设线程是空闲的,可以开始下一个任务

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

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

  • 实现您的自定义
    TaskScheduller
    ,如本文所述
  • 控制更高级别上创建的任务量,例如,使用信号量控制并发任务。你可以找到一个例子
  • 如果您选择第二个选项,我警告您,这只是一个使用信号量的示例。我的意思是,代码不是用于生产的。

    可能重复