2014-10-07 169 views
1

我有一个以预定方式运行作业的控制台应用程序。 作业做两件事情:多线程应用程序和潜在内存泄漏(C#)

1)运行SQL语句 2-)的E-mail声明

如果我运行顺序形式的工作,一切按预期工作,工作的结果运行时,内存消耗会在操作期间增加,然后释放内存,但是如果我并行运行作业,使用任务并行库,在所有作业完成后,与顺序选项相比,内存消耗会保持高得多,并且还会继续执行其他作业增加内存消耗。

要我用下面的试验例更具体的:

依序:(后循环完成,GC被明确地收集用于测试目的的内存消耗是大约55兆字节)

for (int j = 0; j < 3; j++) 
{ 
    for (int i = 0; i < 15; i++) 
    { 
     var job = new BIJob(reportData); 
     job.Execute(); 
    } 
    Thread.Sleep(10000); 
} 

并行: (循环完成后,显式收集GC以用于测试目的内存消耗约为85兆字节)

for (int j = 0; j < 3; j++) 
{ 
    for (int i = 0; i < 15; i++) 
    { 
     Task jobRunTask = Task.Factory.StartNew(() => 
     { 
      var job = new BIJob(reportData); 
      job.Execute(); 

     }); 
    } 
    Thread.Sleep(10000); 
} 

有近似值经过45次迭代后内存消耗差异达到30兆字节,并且并行版本中没有收集额外的内存。

什么可能导致这种行为?任何想法/意见表示赞赏。

+0

您确定您的'job.Execute()'可以处理多线程场景吗? – Natxo 2014-10-07 16:45:23

回答

1

当你并行执行多个操作时,你需要存储足够的内存来处理这些并行操作中的每一个,而不是每次在内存中只有一个工作集。您还有其他线程,每个线程都将消耗内存。

这些操作的内存将不能被回收,直到它们实际完成。你只是开始你的循环中的操作,而不是等待他们完成,所以他们不一定有资格收集,只要你是在检查他们。如果您等待所有的操作到实际上完成那么他们将合格收集,虽然GC当然是免费等待,只要实际上收集他们。

+0

您好Servy,我修改了我的并行代码,以等待任务如下finsh;但是仍然大约相同,那么所有任务完成: 'List tasks = new List (); 对(INT J = 0;Ĵ<3; J ++){ 为 (INT I = 0; I <15;我++){ 任务 = jobRunTask Task.Factory.StartNew(()=> { 变种job = new BIJob(reportData); job.Execute(); }); tasks.Add(jobRunTask); } Thread.Sleep(10000); } Task.WaitAll(tasks.ToArray()); ' – erdem 2014-10-07 16:40:02

+1

@ erdem在任务完成后,内存变为*合格*用于收集,但不一定会立即收集,并且创建的线程池线程在完成使用后不会立即被拆除;随着时间的推移,他们会慢慢释放。首先,你甚至不应该担心这一点。如果你的记忆力确实有问题,你应该只关心自己,而你显然不是。 – Servy 2014-10-07 16:42:58

+0

事情是我使用应用程序作为服务,我每天都在观看内存使用情况。在一批作业同时运行(大约10兆字节)之后,内存消耗量似乎每天都会增加很少,并且从未下降到之前的情况。 (我认为那时候那些任务相关的资源应该已经发布了)。从长远来看,这可能会导致崩溃问题。 – erdem 2014-10-07 16:54:46

0

任务并行库将简单地保留它创建的一些线程,以防它稍后需要它们,因为创建新线程是相对昂贵的操作(无论是在内存和CPU方面)。

关于内存泄漏:只要资源没有压力,TPL就没有理由使用线程池释放任何线程。 如果你想测试一个内存泄漏,你可以简单地增加你的循环次数。循环1000次或1000000次后,内存使用率应该没有差别。

+0

这是线程池,而不是TPL,还要注意线程在闲置一段时间后会被释放。 – Servy 2014-10-07 16:33:42

+0

默认的TPL使用线程池。是的,当然它会在一段时间后释放它们。 – Foxfire 2014-10-07 16:37:38

+0

是的,我的观点是这不是特定于TPL的行为,它比这更普遍化,TPL只是使用具有此行为的线程池。 – Servy 2014-10-07 16:39:47