C# 在dotnet core中批量使用Parallel.For
我在dotnet core中使用httptrigger函数,在那里我获取Json格式的httprequest数据。我需要在Google Merchant center帐户中插入此值。几乎有9000行(每次动态数据)需要插入。如何实现执行速度更快的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
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);
}