[英]Running Tasks in parallel
我無法理解為什么這似乎不能並行運行任務:
var tasks = new Task<MyReturnType>[mbis.Length];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = CAS.Service.GetAllRouterInterfaces(mbis[i], 3);
}
Parallel.ForEach(tasks, task => task.Start());
通過逐步執行,我看到這一行被評估:
tasks[i] = CAS.Service.GetAllRouterInterfaces(mbis[i], 3);
任務開始。 我想將所有新任務添加到列表中,然后並行執行它們。
如果GetAllRouterInterfaces
是一個async
方法,則結果Task
已經啟動(請參閱此答案以獲取更多說明)。
這意味着tasks
將包含多個任務,所有這些任務並行運行,而無需隨后調用Parallel.ForEach
。
您可能希望等待tasks
所有條目完成,可以使用await Task.WhenAll(tasks);
來完成此操作await Task.WhenAll(tasks);
。
因此,您應該以:
var tasks = new Task<MyReturnType>[mbis.Length];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = CAS.Service.GetAllRouterInterfaces(mbis[i], 3);
}
await Task.WhenAll(tasks);
來自評論的更新
看來,盡管GetAllRouterInterfaces
處於async
並返回Task
但它仍在發出同步POST請求(大概在其他任何await
之前)。 這可以解釋為什么在進行此請求時,每次對GetAllRouterInterfaces
調用都GetAllRouterInterfaces
阻塞狀態,因此您獲得的並發度最低。 理想的解決方案是發出一個異步POST請求,例如:
await webclient.PostAsync(request).ConfigureAwait(false);
這將確保您的for
循環不會被阻塞,並且請求是同時進行的。
對話后進一步更新
看來您無法使POST請求成為異步請求,並且GetAllRouterInterfaces
實際上並沒有執行任何異步工作,因此,我建議以下建議:
GetAllRouterInterfaces
刪除async
並將返回類型更改為MyReturnType
像這樣並行調用GetAllRouterInterfaces
var routerInterfaces = mbis.AsParallel() .Select(mbi => CAS.Service.GetAllRouterInterfaces(mbi, 3));
我不知道我是否以正確的方式理解您。
首先,如果GetAllRouterInterfaces返回一個Task,則必須等待結果。
使用Parallel.ForEach,您無法按原樣等待任務,但是可以執行類似的操作:
public async Task RunInParallel(IEnumerable<TWhatEver> mbisItems)
{
//mbisItems == your parameter that you want to pass to GetAllRouterInterfaces
//degree of cucurrency
var concurrentTasks = 3;
//Parallel.Foreach does internally something like this:
await Task.WhenAll(
from partition in Partitioner.Create(mbisItems).GetPartitions(concurrentTasks)
select Task.Run(async delegate
{
using (partition)
while (partition.MoveNext())
{
var currentMbis = partition.Current;
var yourResult = await GetAllRouterInterfaces(currentMbis,3);
}
}
));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.