2014-03-14 81 views
0

我有一个Windows服务,它定期检查新记录的数据库并处理新线程中的每条记录(可能需要长达10分钟)。当服务在启动后立即处于空闲状态时,需要4 MB的RAM。当它开始处理第一条记录时,它会上升到70+ MB,并且即使线程完成时也会停留在那里(我猜没关系,因为这个内存很快会再次需要使用)。然后在下一个请求中,它从70到大约100 MB,并且在线程完成后也停留在那里。 所以我的问题是哪有的东西内存泄漏这样的:c#Windows服务中的内存泄漏?

public partial class MyWinService : ServiceBase 
{ 
    DBService service; 
    IEnumerable<long> unfinishedRequests; 
    List<long> activeRequests; 

    protected override void OnStart(string[] args) 
    { 
     System.Timers.Timer timer1 = new System.Timers.Timer(60000); 
     timer1.Elapsed += Timer_Tick; 
     timer1.Start(); 
     service = new DBService(); 
     activeRequests = new List<long>(); 
    } 

    private void Timer_Tick(object sender, System.Timers.ElapsedEventArgs e) 
    { 
      unfinishedRequests = service.GetUnfinishedRequests(); 
      foreach (var req in unfinishedRequests) 
      { 
       new Thread(delegate() { ProcessRequest(req); }).Start(); 
      } 
    } 

    private void ProcessRequest(long requestID) 
    { 
     activeRequests.Add(requestID); 
     // Lots of webservice calls, XML->XSLT->HTML->PDF, byte arrays, database INSERTs & UPDATEs etc. 
     activeRequests.Remove(requestID); 
    } 
} 

不应该在的ProcessRequest创建的所有对象()方法的线程结束后销毁?如果程序在第一个线程之后已经有100 MB的内存,为什么它要求更多(在我的测试中,输入数据是相同的,所以两个线程应该使用相同数量的内存,我认为)。

回答

2

原来我太依赖于静态辅助类了。一旦我改变静态实例的内存消耗明显下降,GC也能够释放更多的内存

+0

+1 Nice anz,需要更多的重新实施在我的应用程序 – Backtrack

+0

非常intresting,得到了同样的问题 – jonathana

1

有可能出现内存泄漏至少两件事情找到memmory泄漏问题。

首先,您的activeRequests列表不断添加到,但从未调整大小。虽然您从列表中删除项目,但分配用于保存这些项目的内存永远不会被回收。如果您将一百万个项目添加到列表中,然后将其全部删除,则仍然会分配用于存储这些项目的基础内存。

尽管如此,你的清单必须非常大(约400万件)才能达到30兆字节。

你说你的计时器滴答方法可能需要10分钟才能完成。你有一个问题,因为虽然计时器滴答快速完成,它创建的线程可能需要很长时间才能执行。一分钟后另一个计时器滴答声将出现并排队更多的线程。你在这里没有线程限制,所以如果有一千个未完成的请求,你将会缓存1,000个线程。这绝对不是一件好事,而且很可能会以这种方式耗尽内存。

你应该考虑在该循环中使用Parallel.ForEach。例如:

Parallel.ForEach(unfinishedRequests, req => ProcessRequest(req)); 

这将限制并发线程,这将阻止您不必因过度任务切换,你耗尽内存或者使你的系统慢下来这么多的线程数。

我不知道你是否调用内存泄漏实际上是内存泄漏。如果您使用任务管理器来确定进程正在使用的内存量,则不会测量实际的内存使用情况。任务管理器对于发现内存泄漏并不是很有用,除非你真的真的泄漏严重。在SO中搜索有关C#中的内存泄漏检测的信息以获取一些想法。