我正在试验一个定期运行并从远程服务器下载大量数据(只是文本)的网络应用程序(WCF NetTcpBinding)。该应用程序使用 System.Threading.Timer 在 Windows 服务中运行:
protected override void OnStart(string[] args)
{
int interval = // get interval from some config file
timer = new Timer(new TimerCallback(x => DoWork()), null, 0, interval);
}
我观察到的是,当下载大量数据时,服务进程会消耗大约 300,000 kb 的工作集内存(考虑到数据量,这是预期的)。然而,在操作完成后,进程保持在大约 300,000 kb 左右,根据我运行的 CLR 分析器,这是堆栈内存,尽管我不是 100% 确定这一点。
一旦服务在 X 分钟的间隔后进行另一批下载,该过程会回落到大约 15,000 kb 的较低内存使用量,然后只有在有更多数据要下载时才会立即再次上升。但是,如果要下载的数据很少甚至没有,则该过程将继续挂在大约 300,000 kb 左右。
在每个间隔完成后在这种情况下使用 GC.Collect 是否有意义(每个间隔的操作完全相互独立),还是应该由 GC 自己执行?在我看来,GC 会一直等到新批次需要更多内存才能清除旧批次剩余的内存——这本身不是内存泄漏,但 GC 等待的时间比它应该等待的时间长。我很好奇这是设计使然,还是我的代码中可能有某些东西导致了这种行为?此外,如果它实际上是堆栈内存,我的印象是 GC 并没有真正参与。但是我测试了以下代码,它似乎确实及时清除了内存:
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);