[英]Issue with calling async method inside Parallel.Foreach method
我有情況想在paralle.Foreach循環中調用一個asyn方法
public void ItemCheck<T>(IList<T> items,int id)
{
Parallel.ForEach(items, (current) =>
{
PostData(current,id);
});
Console.log("ItemCheck executed")
}
public async void PostData<T>(T obj, int id)
{
Console.lgo("PosstData executed")
}
輸出:
ItemCheck executed
PosstData executed
為什么會這樣發生? 在完成PostData方法的執行之前,先執行下一行。我該如何解決此問題。
為什么會這樣發生?
因為您使用的是async void
。
而且-正如喬恩·斯基特(Jon Skeet)所提到的-在這里進行並行處理毫無意義。 並行處理將工作划分為多個線程。 您真正想要的是並發 ,而不是並行性 ,可以使用Task.WhenAll
來完成:
public async Task ItemCheckAsync<T>(IList<T> items, int id)
{
var tasks = items.Select(current => PostDataAsync(current, id));
await Task.WhenAll(tasks);
}
public async Task PostDataAsync<T>(T obj, int id)
短語“並行”通常用來表示“一次做一件以上的事情”,但是這種用法使您誤以為使用Parallel
,在這種情況下, Parallel
不是合適的工具。 這就是為什么我強烈喜歡術語“並行”並保留Parallel
類所做的事情“並行”的原因之一。
問題在於您的PostData
方法是異步執行的,沒有任何內容告訴並行循環等待所有任務完成。 我將用來同步執行流程的替代方法:
var tasks = items
.AsParallel()
.WithDegreeOfParallelisum(...)
.Select(async item => await PostData(item, id))
.ToArray();
Task.WaitAll(tasks); // this will wait for all tasks to finnish
還有您的異步方法,即使它們無效,它們也應返回Task
而不是void。 這種方法的一個優點是使代碼更明確,此外,您可以將任務用於其他任何操作,例如等待完成。
public async Task PostData<T>(T obj, int id)
您是否還需要並行創建/啟動異步任務,然后等待它們? 這樣的結果就是並行創建任務(這不是繁重的操作,所以為什么要並行執行呢?)。 如果您除了PostData
方法之外沒有在並行循環中做任何其他繁重的工作,我認為您根本不需要並行循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.