Entity Framework 的长时间并行任务会导致高 CPU 峰值和内存使用率

问题描述 投票:0回答:0

我正在将 C# ASP.NET Core 7 项目从使用带有常规 SQL 查询的 MS SQLClient 改为使用 Entity Framework。当应用程序运行多个长时间运行的任务时,我有一个特殊的地方,它是一种带有大 for 循环的模拟,用户可以在其中跟踪进度,因此,每个任务在其自己的任务中数十次写入数据库.旧的 SQLClient 解决方案以最少的 CPU 和内存使用率顺利运行,但使用 EF,一旦线程开始工作,一切都会停止并冻结。

我知道 DbContext 不是线程安全的,因此每个任务都创建自己的 DbContext,并且他们创建它,特别是在发生数据库插入的地方,一旦不需要它们,我会立即处理它们,但是,在 for 循环中它完全冻结了计算机,一切都停止了。 Web 应用程序甚至不再响应。

简化的控制器:

        public SmContext db { get; set; }

        public SimulateRoundModel(SmContext db)
        {
            this.db = db;
        }

        public async Task<IActionResult> OnPost()
        {
            List<Match> matches = new CollectorClass(db).Collect();
            MyClass.Wrapper(matches);
            return Page();
        }

简单代码:

public static void Wrapper(List<Match> matches)
    {
        Parallel.For(0, matches.Count,
               index =>
               {
                   matches[index].LongSim();
               });
    }

比赛类别:


private SmContext db { get; set; }

public Match(db){
this.db = db;
}

public void longSim()
    {
        db.Dispose(); // disposing the main dbcontext that the constructor receives, we don't want to use that

        using (SmContext db = new SmContext())
        {
            // some initial query and insert
        }

        for(int i = 0; i < 100; i++)
        {
            Thread.Sleep(5000);

            // some simulation

            db = new SmContext();

            SomeInsert(); // these are using the db for the insert
            SomeInsert();
            SomeInsert();

            db.Dispose();
        }
    }

我们谈论的是 5-50 场比赛和并行。为了使用旧的 SQLClient 解决方案对它们进行了很好的优化,我之前看到过 200 场比赛没有问题地运行它。这些不是密集的任务,只是简单的东西和一些查询,但它们运行时间很长。理想情况下,我想在不进行重大重写的情况下继续将进度保存到数据库中。

最终的问题是,这里是否存在概念性问题,我是新手无法识别,或者这个解决方案应该可以正常工作并且代码的黑点中出现了一些模糊的地方?

c# asp.net entity-framework
© www.soinside.com 2019 - 2024. All rights reserved.