jok*_*okr 2 c# memory-leaks dependency-injection microsoft.extensions.hosting
我正在编写一个针对 dotnet core 框架 3.1 的应用程序。我使用依赖注入来配置数据库上下文等。在我的 Program.cs 中,我有以下代码:
var host = new HostBuilder()
    .ConfigureHostConfiguration(cfgHost =>
    {
        ...
    })
    .ConfigureAppConfiguration((hostContext, configApp) =>
    {
        ....
    })
    .ConfigureServices((hostContext, services) =>
    {
        ...
        services.AddDbContext<MyHomeContext>(options =>
        {
            options.UseNpgsql(hostContext.Configuration.GetConnectionString("DbContext"));
        }, ServiceLifetime.Transient);
        ...
    })
    .ConfigureLogging((hostContext, logging) =>
    {
        ...    
    })
    .Build();
我转到host另一个班级。在另一个类中,作为较长方法的一部分,我有以下代码:
    using (var context = Host.Services.GetService(typeof(MyHomeContext)) as MyHomeContext)
    {
        StatusValues = context.Status.ToDictionary(kvp => kvp.Name, kvp => kvp.Id);
    }
    GC.Collect();
    GC.Collect();
这些GC.Collect电话是出于测试/调查目的。在MyHomeContextI 中,出于测试目的,实现了析构函数和 Dispose() 的重写。Dispose() 被调用,但析构函数永远不会被调用。这会导致我创建的每个实例出现内存泄漏MyHomeContext。
我缺少什么?MyHomeContext我可以做什么来确保当我不再需要它时删除它的实例。
我转向这个工具有几个原因:
当我替换Host.Services.GetService(typeof(MyHomeContext)) as MyHomeContext为正在调用的new MyHomeContext()析构函数时。MyHomeContext在我看来,依赖注入框架中的某些东西保存着对该对象的引用。这是真的?如果是这样,我该如何告诉它释放它?
很难对你的问题给出一个好的答案,因为有很多误解需要解决。以下是一些需要注意的事项:
\nGC.Collect()将无法清除context同一方法引用的变量。Dispose调用其方法时将抑制对终结器的调用。这是通过调用GC.SuppressFinalize来完成的。实体框架DbContext正确实现了 Dispose 模式,这也会导致您看不到终结器被命中。context被取消引用并且有资格进行垃圾收集,终结器也不太可能在调用GC.Collect(). 但是,您可以通过调用GC.WaitForPendingFinalizers()停止应用程序并等待调用终结器。呼唤WaitForPendingFinalizers几乎不是您想要做的事情,但它对于测试和基准测试目的非常有用。除了这些 CLR 特定部分之外,这里还有一些关于 DI 部分的反馈:
\nIServiceScope. 服务缓存在这样的范围内,当该范围被处置时,它将确保其缓存的一次性服务也被处置,并且它将确保以与创建相反的顺序完成此操作。Host.Services在您的情况下)请求服务是一个坏主意,因为它会导致作用域服务(例如您的DbContext)被缓存在根容器中。这使它们实际上成为单身人士。换句话说,DbContext无论您从Host.Services. 这可能会导致各种难以调试的问题。解决方案再次是创建一个范围并从该范围进行解析。示例:\nvar factory = Host.Services.GetRequiredService<IServiceScopeFactory>();\nusing (var scope = factory.CreateScope())\n{\n    var service = scope.ServiceProvider.GetRequiredService<ISomeService>();\n    service.DoYourMagic();\n}\n| 归档时间: | 
 | 
| 查看次数: | 1890 次 | 
| 最近记录: |