C# 在dotnet core中批量使用Parallel.For

C# 在dotnet core中批量使用Parallel.For,c#,.net-core,parallel.foreach,azure-function-async,C#,.net Core,Parallel.foreach,Azure Function Async,我在dotnet core中使用httptrigger函数,在那里我获取Json格式的httprequest数据。我需要在Google Merchant center帐户中插入此值。几乎有9000行(每次动态数据)需要插入。如何实现执行速度更快的Parallel.for逻辑。目前我使用的每个循环如下,但它需要更多的时间。 下面是代码 string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); dynamic bo

我在dotnet core中使用httptrigger函数,在那里我获取Json格式的httprequest数据。我需要在Google Merchant center帐户中插入此值。几乎有9000行(每次动态数据)需要插入。如何实现执行速度更快的Parallel.for逻辑。目前我使用的每个循环如下,但它需要更多的时间。 下面是代码

string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic body = JsonConvert.DeserializeObject(requestBody);
for (int i =0;i<body.Count;i++)
{
  Product newProduct = InsertProduct(merchantId, websiteUrl,body[i]);
}
string requestBody=等待新的StreamReader(req.Body).ReadToEndAsync();
DynamicBody=JsonConvert.DeserializeObject(requestBody);
对于(inti=0;i进行此操作

string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic body = JsonConvert.DeserializeObject(requestBody);
Parallel.For(0, body.Count, i => {
    Product newProduct = InsertProduct(merchantId, websiteUrl,body[i]);
});

我创建了一个小例子,也许在那里你可以找到最适合你的情况的最佳方式

有3种选择:

依次 正如标题所述,每个项目都是按顺序处理的。非常节省的方法,但不是处理9000个项目的最快方法:)

使用异步等待 我认为在你的例子中,这最适合你。每个项目都是并行处理的,直接启动处理并启动一个
任务
。()

…更新 谢谢你的评论。我已将async await实现更新为更简单的实现:

private static async Task ForEachAsync<T>(IEnumerable<T> enumerable, Func<T, int, Task> asyncFunc)
{
    var itemsCount = enumerable.Count();
    var tasks = new Task[itemsCount];
    int i = 0;
    foreach (var t in enumerable)
    {
        tasks[i] = asyncFunc(t, i);
        i++;
    }
    await Task.WhenAll(tasks);
}
private静态异步任务ForEachAsync(IEnumerable enumerable,Func async)
{
var itemscont=enumerable.Count();
var tasks=新任务[itemsCount];
int i=0;
foreach(可枚举中的var t)
{
tasks[i]=asyncFunc(t,i);
i++;
}
等待任务。何时(任务);
}
并将
最大并行度
设置为1。这对并行处理有着巨大的影响,如本文中所述


您是否尝试过将(int i=0;i
替换为(0,body.Count,i=>{…})的
Parallel.for?您的意思是,我应该这样写。它是自动作为同步调用还是我必须定义异步?Parallel.For(0,body.Count,i=>{Product newProduct=InsertProduct(merchantId,websiteUrl,body[i]);我将如何定义最大并行度?从哪里开始?您熟悉吗?如果没有,最好忘记async/await,尝试同步完成工作。Async/await有一些陷阱,如果您不熟悉它,您很可能会陷入其中至少一个陷阱。要配置并行度,请创建一个
ParallelOptions
对象,设置其
maxDegreeofpparallelism
属性,然后将该对象作为参数传递给
Parallel。For
方法。如果您想知道我说的陷阱是什么,可以查看此处:,或任何.XYZ
并行.XYZ
都是为CPU限制的操作而设计的。我假设
InsertProduct
执行一个受I/O限制的数据库操作。如果你想同时执行多个I/O绑定操作,那么你应该考虑使用相关的数据库驱动程序的异步I/O,并用“代码>任务”发出异步操作。如果代码>正文包含很多产品,您也可能需要考虑使用节流来缓冲数据库。<代码>并行。对于是为CPU绑定操作而设计的。我确实相信
InsertProduct
更受I/O的限制。@PeterCsala,这个问题专门问了如何使用Parallel。答案是什么。感谢您指出这一点。示例中的
并行.for
测量显示了饱和
线程池的效果。没有
线程池
线程可用于执行
任务的延续。延迟
任务,因此在通过算法将新线程注入池之前无法取得任何进展。大约每500毫秒发生一次。这就是为什么在使用
Parallel.For
Parallel.ForEach
方法时应该指定
maxdegreeofpparallelism
的原因。此外,示例中的
ForEachAsync
实现存在缺陷。您应该在每次测量之前初始化
\u数据库
,并在测量结束后对其进行验证,以确保所有元素都已处理。@TheodorZoulias感谢您的评论我已经更新了答案,当然还有错误的异步等待实现(这只是另一个SO问题的副本)。
var list = GenerateItems();
var count = list.Count();
var options = new ParallelOptions{MaxDegreeOfParallelism = MAX_DEGREE_OF_PARALLELISM};
Parallel.For(0, count, options, (i) => 
{
    InsertInDatabaseAsync($"{i}", list.ElementAt(i)).GetAwaiter().GetResult();
});
var list = GenerateItems();
var count = list.Count();

// Extensions method see in referenced SO answer
ForEachAsync(count, list, async (item, index) => 
{
    await InsertInDatabaseAsync($"{index}", item);
}).GetAwaiter().GetResult();
private static async Task ForEachAsync<T>(IEnumerable<T> enumerable, Func<T, int, Task> asyncFunc)
{
    var itemsCount = enumerable.Count();
    var tasks = new Task[itemsCount];
    int i = 0;
    foreach (var t in enumerable)
    {
        tasks[i] = asyncFunc(t, i);
        i++;
    }
    await Task.WhenAll(tasks);
}