运行异步 Foreach 循环 C# async await

mic*_*ael 5 c# asynchronous async-await

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

基本上,我拥有的是一个我需要处理的对象列表,处理过程涉及遍历其属性并连接字符串,然后创建一个新对象(在这种情况下称为 trellocard)并最终添加一个 trellocard 列表。

迭代需要很长时间,所以我想做的是异步处理多个对象。

我尝试了多种方法,但基本上我想做这样的事情。(在下面的例子中,我已经删除了处理,只是把 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();
    }
Run Code Online (Sandbox Code Playgroud)

Mri*_*boj 7

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

简单的定义是,Async-Await 是 .Net 并发的一部分,可用于进行多个 IO 调用,并且在处理过程中不会浪费用于 Compute 操作的线程。就像调用数据库、Web 服务、网络调用、文件 IO,所有这些都不需要当前进程线程

在您当前的情况下,用例是:

  1. 迭代其属性并连接字符串,然后创建一个新对象
  2. 最终添加一个trellocards列表

这似乎是一个计算绑定操作,除非您正在执行 IO,否则在我看来您似乎正在遍历内存对象,对于这种情况,更好的选择是:

  1. Parallel.ForEach,为了并行化内存处理,虽然你需要小心竞争条件,因为给定的内存可以被多个线程访问,从而在写操作期间特别破坏它,所以至少在当前代码中使用线程安全集合像ConcurrentBag来自System.Collections.Concurrent命名空间,或者适合用例而不是List<TrelloCard>,或者您可以考虑遵循线程安全列表

另请注意,如果您的方法不是默认的Async,那么您可能计划将它们包装在一个Task.Run, 到awaiton 中,尽管这需要一个线程池线程,但可以使用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();
    }
Run Code Online (Sandbox Code Playgroud)


Ale*_*ese 5

如果您希望它们并行运行,您可以为每个操作生成一个新任务,然后等待所有使用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();
    });
}
Run Code Online (Sandbox Code Playgroud)