【问题标题】:C# Async Foreach loop for huge volume of data用于大量数据的 C# 异步 Foreach 循环
【发布时间】:2016-12-15 21:29:52
【问题描述】:

我必须在批处理作业中处理大量数据

程序流程

var inputDataLst = contextObj.GetData(); //More that 10000 rows I will retrieve

foreach(var item in inpDataLst)
{
     //logic
}

Call context.SaveMethod(inpuDataLst);

我正在尝试做类似的事情

var tsklst = inputDataLst.Select(async pItem => 
{
   //Logic
});

await Task.WhenAll(taskList);

编译器发出警告,Resharper 建议我创建一个同步方法。

任何人都可以建议我如何处理这个问题,因为我将拥有大量数据,我想做一个异步操作..

实施@bruno 建议

Parallel.ForEach(taskList, item => {
 item.StatusId = 2; //Completed
 LastUpdateUser = "Batch";
});

循环完成后,我得到 taskList 为 NULL,

【问题讨论】:

  • 您真正追求的是异步还是并行?你在逻辑上做什么?如果它不使用共享状态,你可以只使用 Linq 的 IEnumerable.AsParallel() 方法,或者你可以使用 Parallel.For
  • 我不想一一处理那条记录..
  • 你能显示编译器正在显示的警告吗?
  • 是的,我很确定他的意思是并行...
  • @oqx 代码上的全绿线..也许 resharper 正在发出警告..

标签: c# .net async-await parallel.foreach


【解决方案1】:

您应该为此使用Parallel.For。它将异步处理您的列表。

var inputDataLst = contextObj.GetData(); 


Parallel.For(0, inputDataLst.Length,
                index=> 
                {
                    //your logic, something like ProcessData(inputDataLst[index])
                });

context.SaveMethod(inpuDataLst);

你也可以使用Parallel.ForEach:

Parallel.ForEach(inpuDataLst, item => { ProcessData(item) });

编辑:

根据您的编辑附加评论,我写了一个非常简单的最小工作示例:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;

namespace SO.RajGan
{
    class SomeData
    {
        public int StatusId { get; set; }
        public string LastUpdateUser { get; set; }

        public override string ToString()
        {
            return $"Last update user: {LastUpdateUser}; Status ID = {StatusId}";
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var dataList = new List<SomeData>();

            for(int i = 0; i < 100000; i++)
            {
                dataList.Add(new SomeData() { StatusId = new Random(i).Next(1, 10), LastUpdateUser = $"User {i + 1}" });
            }

            Parallel.ForEach(dataList, item => 
            {
                item.LastUpdateUser = "Batch";
                item.StatusId = 2;
            });

            Debug.Assert(dataList != null);
        }
    }
}

我对其进行了测试并且它有效,dataList 不为空,并且所有条目都相应更新。如果没有看到代码,我无法追踪您的列表为空的原因。

【讨论】:

  • 感谢布鲁诺,我尝试实施您的解决方案并返回 null。我将在 processdata() 方法中所做的只是更改项目属性中的值。所以我希望更改应该反映在 inputDataList 中。但我越来越空了。我已经更新了上面的代码..
  • 是的,它对我有用。对不起,我犯了一个非常愚蠢的错误。 contextObj.GetData();正在返回 Ienumerable,我看到它无法并行保留 vaule.Foreach。但是当我返回 LIst 然后它工作正常..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
  • 2013-09-27
  • 2020-10-13
相关资源
最近更新 更多