簡體   English   中英

在Parallel.Foreach方法中調用異步方法的問題

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM