后台服务/工作者不要垃圾收集

时间:2019-03-23 22:59:29

标签: c# garbage-collection resources backgroundworker asp.net-core-hosted-services

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

我已经做了所有想得到的事情,包括让我的所有任务都返回一些值,并在可能的情况下使用使用语句。还使用Dependency Injection抽象了几层,(以确保有多个地方应该与运行时进行通信以适合运行垃圾回收。

我唯一的“解决方案”(不是解决方案)是手动运行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();
            }
        }
    }
}

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


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

1 个答案:

答案 0 :(得分:1)

这是服务器GC的预期行为。对其进行了调整,以充分利用可用内存,因此除非真正需要它,否则不会收集。那真的是问题吗?该操作系统能够根据需要调入和调出内存,因此,如果您以64位运行,则在大多数情况下都不会产生影响。如果仍然值得关注,则有几种选择:

  • 最简单的解决方案是切换到工作站GC,此工作站更具竞争性并会定期自动收集内存。将gcServer setting设置为false将激活工作站GC
  • 您可以使用GC分配的堆数。如果CPU具有大量内核,则可能会产生明显的影响。可以使用GCHeapCount设置来完成。有关更多信息,请参见毛尼·史蒂芬斯(Maoni Stephens)的this article
  • 您可以创建a Windows job来限制该进程可用的内存。但是,据我所知,这要复杂得多,因为Windows中没有内置工具可以做到这一点

.NET Core 3.0将带来新的设置来调整GC,以适应内存不足的情况,但是它不会在第二学期之前发布。