2

我有一個代碼可以爲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://stackoverflow.com/questions/11138927/best-way-to-limit-the-number-of-主動任務運行,通過最並行任務天秤座) – cassandrad

回答

0

您對MaxDegreeOfParallelism的預測不正確,請參閱this的文章,這就是爲什麼您可以看到同時啓動2000個線程的原因。當Await Task.Delay(1000).ConfigureAwait(False)被執行時,線程被認爲是空閒的並且可以開始下一個任務。

我想要做的是限制可以觸發的任務的數量。

你必須自己去實現它。你可以採取兩種方法:

  1. 實現自定義TaskSchedullerthis文章。
  2. 控制較高級別創建的任務的數量,例如,使用信號量來控制併發任務。示例,您可以找到here

如果你會選擇第二個選項,我警告你,這只是一個信號量工作的例子。我的意思是,代碼不適用於生產。