簡體   English   中英

運行Async Foreach循環C#異步等待

[英]Running Async Foreach Loop C# async await

我正在努力掌握c#async等待的基本概念。

基本上我所擁有的是一個我需要處理的對象列表,處理包括迭代其屬性並連接字符串,然后創建一個新對象(在本例中稱為trellocard)並最終添加一個trellocards列表。

迭代需要很長時間,所以我想做的是異步處理多個對象。

我嘗試了多種方法,但基本上我想做這樣的事情。 (在下面的例子中我已經刪除了處理,只是把system.threading.thread.sleep(200)。我等待這不是一個異步方法,我可以使用tasks.delay,但重點是我的處理沒有有任何異步方法,我想只使用多個實例運行整個方法。

    private async Task<List<TrelloCard>> ProcessJobs(IQueryable<IGrouping<CardGrouping, Job>> jobs)
    {
        List<TrelloCard> cards = new List<TrelloCard>();

        foreach (var job in jobs.ToList())
        {
           card = await ProcessCards(job, cards);  // I would like to run multiple instances of the processing
           cards.add(card); //Once each instance is finshed it adds it to the list
        }


  private async Task<TrelloCard> ProcessCards(Job job)
    {
        System.Threading.Thread.Sleep(2000);  //Just for examples sake

        return new TrelloCard();
    }

我正在努力掌握c#async等待的基本概念。

簡單的定義是,Async-Await是一部分.Net並發,可用於進行多個IO調用,並且在此過程中不會浪費用於計算操作的線程。 它就像調用數據庫,Web服務,網絡調用,文件IO一樣,所有這些都不需要當前的進程線程

在您目前的情況下,用例是:

  1. 迭代其屬性並連接字符串,然后創建一個新對象
  2. 最終添加了一個trellocards列表

這似乎是一個計算綁定操作,除非你正在做一個IO,對我來說似乎你正在遍歷一個內存對象,對於這種情況,更好的選擇是:

  1. Parallel.ForEach ,要並行處理內存處理,雖然你需要注意Race條件,因為給定的內存可以被多個線程訪問,因此在寫操作期間特別破壞它,所以至少在當前代碼中使用Thread safe collection像System.Collections.Concurrent命名空間中的ConcurrentBag ,或者適合用例而不是List<TrelloCard> ,或者您可以考慮遵循線程安全列表

另請注意,如果您的方法不是默認的Async ,那么您可能計划將它們包裝在Task.Runawait ,雖然這需要一個線程池線程,但可以使用Async-Await調用

Parallel.Foreach代碼用於你的用例(我正在做直接替換,你的代碼似乎有問題,因為ProcessCards函數,只需要Job對象,但你也傳遞了收集Cards ,這是編譯錯誤):

 private List<TrelloCard> ProcessJobs(IQueryable<IGrouping<CardGrouping, Job>> jobs)
    {
        ConcurrentBag<TrelloCard> cards = new ConcurrentBag<TrelloCard>();

        Parallel.ForEach(jobs.ToList(), (job) => 
        {
           card = ProcessCards(job);  // I would like to run multiple instances of the processing
           cards.Add(card); //Once each instance is finshed it adds it to the list
        });

           return cards.ToList();
   }

  private TrelloCard ProcessCards(Job job)
    {
       return new TrelloCard();
    }

如果您希望它們並行運行,您可以為每個操作生成一個新任務,然后使用Task.WhenAll等待所有操作的完成。

private async Task<List<TrelloCard>> ProcessJobs(IQueryable<IGrouping<CardGrouping, Job>> jobs)
{
    List<Task<TrelloCard>> tasks = new List<Task<TrelloCard>>();

    foreach (var job in jobs)
    {
        tasks.Add(ProcessCards(job));
    }

    var results = await Task.WhenAll(tasks);

    return results.ToList();
}


private Task<TrelloCard> ProcessCards(Job job)
{
    return Task.Run(() =>
    {
        System.Threading.Thread.Sleep(2000);  //Just for examples sake

        return new TrelloCard();
    });
}

jobs.ToList()只是在浪費內存。 它已經是IEnumerable所以可以在foreach

ProcessCards無法編譯。 你需要這樣的東西

    private Task<TrelloCard> ProcessCards(Job job)
    {
        return Task.Run(() =>
        {
            System.Threading.Thread.Sleep(2000);  //Just for examples sake

            return new TrelloCard();
        });
    }

現在你想要ProcessJobs

  • 為每個作業創建ProcessCards任務
  • 等待所有任務完成
  • 返回一系列TrelloCard

     private async Task<List<TrelloCard>> ProcessJobs(IQueryable<IGrouping<CardGrouping, Job>> jobs) { return await Task.WhenAll(jobs.Select(ProcessCards)); } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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