我在使用 task/await 的 foreach 中有一些耗时的代码。 它包括从数据库中提取数据、生成 html、将其发布到 API 以及将回复保存到数据库。
模型看起来像这样
List<label> labels = db.labels.ToList();
foreach (var x in list)
{
var myLabels = labels.Where(q => !db.filter.Where(y => x.userid ==y.userid))
.Select(y => y.ID)
.Contains(q.id))
//Render the HTML
//do some fast stuff with objects
List<response> res = await api.sendMessage(object); //POST
//put all the responses in the db
foreach (var r in res)
{
db.responses.add(r);
}
db.SaveChanges();
}
就时间而言,生成 Html 并将其发布到 API 似乎花费了大部分时间。
理想情况下,如果我可以为下一个项目生成 HTML,并等待帖子完成,然后再发布下一个项目,那就太好了。
也欢迎提出其他想法。 如何解决这个问题?
我首先想到的是在 foreach
上方添加一个 Task
并等待它完成,然后再进行下一次 POST,但是我该如何处理最后一个循环.. .感觉很乱...
最佳答案
您可以并行执行,但您需要在每个任务中使用不同的上下文。
Entity Framework 不是线程安全的,因此如果您不能在并行任务中使用一个上下文。
var tasks = myLabels.Select( async label=>{
using(var db = new MyDbContext ()){
// do processing...
var response = await api.getresponse();
db.Responses.Add(response);
await db.SaveChangesAsync();
}
});
await Task.WhenAll(tasks);
在这种情况下,所有任务都将并行运行,并且每个任务都有自己的上下文。
如果您不为每个任务创建新的上下文,您将在这个问题 Does Entity Framework support parallel async queries? 中得到错误提示
关于c# - foreach 循环中任务/等待的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31714635/