编程c#:Parallel.Foreach内存消耗管理

时间:2016-03-22 07:36:18

标签: c# entity-framework memory parallel-processing

我想使用Parallel.Foreach机制来确保CPU充分利用CPU密集型任务。我一次从数据库中查询大量对象(每次迭代中只有一个对象,每个对象相当小),然后对该对象执行大量基于CPU的操作,之后我将其保存回来到数据库。

我在数据模型方面使用实体框架,并且考虑到我查询的对象数量,我为每次迭代创建一个新的Context(这是为了限制内存消耗):

    foreach (var id in idlist)
    {
        using (var ctx = new Context())
        {
            var model = ctx.Models.First(x => x.Id == id);
            await model.GlobalRefresh(true); //CPU heavy operation.
            await model.SaveAsync(); //Additional CPU heavy operation.
            ctx.SaveChanges(); //Save the changes
        } //Dispose of the model and the context, to limit memory consumption
    }

这在同步实现中很有效,因为在每次迭代之后,从数据库查询的模型和实体框架上下文都被处理掉。因此,在此过程中我的内存消耗几乎是恒定的,这很好。如果我不以这种方式创建上下文,我会快速耗尽内存(500多个对象)。

当我按如下方式并行设置上述内容时,我的内存消耗量一直很高,因为似乎每次迭代的上下文都没有在下一次迭代继续之前处理(我确实看到了预期的更好的CPU利用率) :

        Parallel.ForEach(idlist, async (id) =>
        {
            using (var ctx = new Context())
            {
                var model = ctx.Models.First(x => x.Id == id);
                await model.GlobalRefresh(true);
                await model.SaveAsync();
                ctx.SaveChanges();
            }
        });

从内存的角度来看,这不一定是个问题,只要所有模型对象不会立即加载到内存中(这实际上也是并行循环的整个点,在一个加载时不止一个时间)。但是,有什么方法可以更好地管理这个过程,例如当内存消耗达到例如75%,以避免Out of Memory异常?

1 个答案:

答案 0 :(得分:0)

TL; DR::可以在下次操作之前使用MemoryFailPoint检查是否有足够的内存。 Microsoft Docs有一个很好的示例here

我最近有一个类似的问题。在检查较旧应用程序的日志时,我注意到一些“内存不足异常”。事实证明,开发人员引入了一些并行编程,以使应用程序更快。因此,也许该应用程序运行速度更快,但是它现在消耗的内存速度更快,并且达到了memory limit for 32-bit app(大约2GB),然后出现了内存不足的异常情况。