后台服务/工作人员不进行垃圾收集

Fra*_*gen 3 c# resources garbage-collection backgroundworker asp.net-core-hosted-services

我需要一个 IHostedService 或“工作服务”,但我遇到了一个有趣的难题,那就是垃圾收集器没有在“适当”的时间运行。相反,它只是不收集任何资源,导致应用程序的内存使用量增加(在调试期间,根本没有发生 GC)。

我已经做了所有能想到的事情,包括让所有任务返回一些值,以及尽可能使用 using 语句。还使用依赖注入抽象了几个层(以确保有多个位置应该与运行时通信,表明它适合运行垃圾收集。

我唯一的“解决方案”(不是解决方案)是手动运行 GC.Collect();

namespace Worker
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation($"Worker running at: {DateTime.Now}");

                var files = Directory.EnumerateFiles(@"C:\\repos\");

                var date = files.Select(f => File.ReadAllBytesAsync(f));

                GC.Collect();
            }
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

结果是,我的代码在不手动触发 GC 的情况下会膨胀到最大可用内存,但是,使用手动 GC 可以运行数小时,而资源使用情况不会发生明显变化


解决方案 使用本文中提到的设置:https://dotnet.github.io/orleans/1.5/Documentation/Deployment-and-Operations/Configuration-Guide/Configuring-.NET-Garbage-Collection.html(已弃用)

更新的链接:https://learn.microsoft.com/en-us/dotnet/core/run-time-config/garbage-collector

Kev*_*sse 5

这是服务器 GC 的预期行为。它被调整为充分利用可用内存,因此除非确实需要,否则不会收集。这真的是问题吗?操作系统能够根据需要对内存进行分页调入和调出,因此,如果您在 64 位中运行,则在大多数情况下不会产生影响。如果这仍然是一个问题,还有一些替代方案:

  • 最简单的解决方案是切换到工作站 GC,这种方法更加积极,并且会定期自动收集内存。将设置设置gcServerfalse激活工作站 GC
  • 您可以使用 GC 分配的堆数量。如果 CPU 具有大量核心,这可能会产生明显的影响。这可以使用设置来完成GCHeapCount。有关更多信息,请参阅毛尼·斯蒂芬斯的这篇文章
  • 您可以创建Windows 作业来限制进程可用的内存。然而,这要复杂得多,因为据我所知,Windows 中没有内置工具可以做到这一点

.NET Core 3.0将带来新的设置来针对低内存场景调整GC,但不会在第二学期之前发布。