我正在尝试使用asp.net core 2.1实现自托管的Web服务,并陷入了实现后台长时间执行任务的问题。
由于每个ProcessSingle
方法的高CPU负载和时间消耗(在下面的代码段中),我想限制同时执行任务的数量。但是我可以看到Parallel.ForEach
中的所有任务几乎立即开始,尽管我设置了MaxDegreeOfParallelism = 3
我的代码是(简化版):
public static async Task<int> Work()
{
var id = await CreateIdInDB() // async create record in DB
// run background task, don't wait when it finishes
Task.Factory.StartNew(async () => {
Parallel.ForEach(
listOfData,
new ParallelOptions { CancellationToken = token, MaxDegreeOfParallelism = 3 },
async x => await ProcessSingle(x));
});
// return created id immediately
return id;
}
public static async Task ProcessSingle(MyInputData inputData)
{
var dbData = await GetDataFromDb(); // get data from DB async using Dapper
// some lasting processing (sync)
await SaveDataToDb(); // async save processed data to DB using Dapper
}
如果我理解正确,那么问题出在Parallel.ForEach中的async x => await ProcessSingle(x)
中,不是吗?
有人可以描述一下,如何以正确的方式实施它吗?
更新
由于我的问题中存在某种歧义,因此有必要关注以下主要方面:
ProcessSingle
方法中包含三个部分:
从数据库异步获取数据
进行长时间的高CPU负载数学计算
将结果保存到数据库异步
问题由两个单独的部分组成:
如何减少CPU使用率(例如,通过运行不超过三个数学同时计算)?
如何保持ProcessSingle
方法的结构-由于异步DB调用而使它们保持异步。
希望现在会更清楚。
P.S。已经给出了合适的答案,它可以工作(特别是感谢@MatrixTai)。编写此更新用于一般性说明。
答案 0 :(得分:0)
如果您更熟悉“传统”并行处理概念,请像这样重写您的ProcessSingle()方法:
public static void ProcessSingle(MyInputData inputData)
{
var dbData = GetDataFromDb(); // get data from DB async using Dapper
// some lasting processing (sync)
SaveDataToDb(); // async save processed data to DB using Dapper
}
当然,您最好也以类似的方式更改Work()方法。