【问题标题】:Ninject with EF multithreadingNinject 与 EF 多线程
【发布时间】:2020-02-02 21:04:49
【问题描述】:

大家早上好!

我刚开始在我发现存在内存泄漏的项目中工作。 情况如下。有一个控制台应用程序基本上一直在while(true) 循环中运行。

有一堆类在循环中执行一些逻辑。 每个类都有 Execute() 方法,其中 create 使用 Task.Run() 方法,其中任何人都不会等待调用。 上述类的列表称为引擎。所有引擎都是无状态类,存储在主 Program.cs 类的数组中。

代码基本上是这样的:

private static List<BaseEngine> Engines;

public static void Main(string[] args)
    {
        InitializeDI();
        RunProgram();
    }
    private static void RunProgram()
    {
        while (true)
        {
            try
            {
                foreach (var engine in Engines)
                {
                    engine.Execute();
                }
            }
            catch (Exception ex)
            {
                //handle
            }
            finally
            {
                Thread.Sleep(TimeSpan.FromSeconds(3));
            }
        }
    }

    private static void InitializeDI()
    {
        _kernel = new StandardKernel();
        ServiceLocator.SetLocatorProvider(() => new NinjectServiceLocator(_kernel));
        NinjectConfig.Setup(_kernel);
    }

示例引擎如下所示:

public class SampleEngine : BaseEngine
        {
            public override void Execute(Task task)
            {
                var someService = ServiceLocator.Current.GetInstance<IDbContext>();

                System.Threading.Tasks.Task.Run(() =>
                {
                    // some action using dbcontext
                });
            }
        }

在上面的 SampleEngine 示例中,它用于从 Ninject DI 获取 IDbContext。但是其他引擎可以使用在 DI 中注册的其他服务。

所有的依赖都注册为InCallScope()

基本上它就像所有引擎一样,它关于着火并且忘记了使用 Task.Run() 的给定方法。 我所做的是更改 Execute 方法以返回任务,并且在此任务运行完成后,我曾经Dispose()此任务。这没有带来任何价值。

我做了一些调查,发现问题出在Ninject.Activation.Cache 内部。我可以手动清理缓存,这会有所帮助,但我知道问题出在代码中,但我找不到。

由于每个依赖项都注册为 InCallScope(),因此它们应该在每个任务开始到结束后被释放。我没有看到任何对这些对象的引用,因为每个引擎都是无状态的。

我使用 ANTS 来查看一些信息,而且这些信息每分钟都在增长:

这指向 Ninject 缓存如下:

看起来 DbContext 没有被释放并且仍然存在于 Ninject 缓存中。是系统任务多的问题还是我做错了什么?

提前致谢 干杯!

【问题讨论】:

    标签: c# multithreading ninject


    【解决方案1】:

    最简单的方法似乎是将 using 嵌入到您的任务中。但这是盲目的,因为您的代码似乎被简化了。您没有在方法中使用task 参数。

    public class SampleEngine : BaseEngine
    {
         public override void Execute(Task task)
         {    
           System.Threading.Tasks.Task.Run(() =>
           {
             using (var someService = ServiceLocator.Current.GetInstance<IDbContext>())
             {
               // some action using dbcontext
             }
           });
         }
    }
    

    对于更高级的方法,这里是an interesting link。它具有InTaskScope 绑定。它基于 AsyncLocal 和通过 TaskFactory 的扩展自定义任务

    【讨论】:

      猜你喜欢
      • 2012-12-26
      • 1970-01-01
      • 1970-01-01
      • 2011-03-29
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多