多线程应用程序和潜在内存泄漏(C#)

多线程应用程序和潜在内存泄漏(C#),c#,.net,multithreading,memory-leaks,task,C#,.net,Multithreading,Memory Leaks,Task,我有一个控制台应用程序,可以按计划方式运行作业。 一份工作做两件事: 1-)运行SQL语句 2-)通过电子邮件发送该声明的结果 如果我按顺序运行作业,一切都会按预期运行,作业运行时,内存消耗会增加,然后释放内存,但是如果我使用任务并行库并行运行作业,在所有作业完成后,内存消耗比顺序选项高得多,额外的作业也会继续增加内存消耗 更具体地说,我使用了以下测试用例: 顺序:(循环完成后,为了测试目的显式收集GC,内存消耗约为55 MB) for(int j=0;j

我有一个控制台应用程序,可以按计划方式运行作业。 一份工作做两件事:

1-)运行SQL语句 2-)通过电子邮件发送该声明的结果

如果我按顺序运行作业,一切都会按预期运行,作业运行时,内存消耗会增加,然后释放内存,但是如果我使用任务并行库并行运行作业,在所有作业完成后,内存消耗比顺序选项高得多,额外的作业也会继续增加内存消耗

更具体地说,我使用了以下测试用例:

顺序:(循环完成后,为了测试目的显式收集GC,内存消耗约为55 MB)

for(int j=0;j<3;j++)
{
对于(int i=0;i<15;i++)
{
var作业=新的BIJob(报告数据);
job.Execute();
}
睡眠(10000);
}
并行:(循环完成并显式收集GC以进行测试后,内存消耗约为85 MB)

for(int j=0;j<3;j++)
{
对于(int i=0;i<15;i++)
{
Task jobRunTask=Task.Factory.StartNew(()=>
{
var作业=新的BIJob(报告数据);
job.Execute();
});
}
睡眠(10000);
}
在45次迭代之后,内存消耗大约有30兆字节的差异,并且并行版本中没有收集额外的内存


是什么导致了这种行为?任何想法/意见都非常感谢。

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


这些操作的内存在实际完成之前无法回收。您只是开始循环中的操作,而不是等待它们完成,因此,无论何时检查它们,它们都不一定符合收集条件。如果您等待所有操作实际完成,则它们将符合收集条件,尽管GC当然可以自由地等待,只要它想实际收集它们。

任务并行库只需保留它创建的一些线程,以备以后需要,因为创建新线程是一项相对昂贵的操作(无论是在内存还是CPU方面)

关于内存泄漏:只要资源没有压力,TPL使用的线程池就没有理由释放任何线程。
如果要测试内存泄漏,只需增加循环数即可。在循环1000次或1000000次之后,内存使用应该没有差别。

这是线程池,而不是TPL,还要注意的是,线程在空闲一段时间后将被释放。TPL默认使用线程池。是的,当然它会在一段时间后释放它们。是的,我的观点是,这不是TPL特有的行为,它更一般化,TPL只是使用线程池,它有这种行为。问题是,他为什么会经历这种行为,而不是由哪个内部组件负责;)嗨,Servy,我修改了我的并行代码,等待任务完成,如下所示;但是,在所有任务完成后仍然大致相同:
List tasks=new List();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();});tasks.Add(jobRunTask);}Thread.Sleep(10000);}Task.WaitAll(tasks.ToArray())
@erdem任务完成后,内存就有资格收集,但不一定会立即收集,创建的线程池线程也不会在使用完后立即拆除;当它们闲置时,它们会随着时间慢慢释放。你根本不应该担心这些。如果你的内存确实存在问题,那么你应该只关心你自己,而你显然不是。问题是我将应用程序作为一种服务使用,我每天都观察内存的使用情况。在一批作业并行运行(大约10兆字节)之后,内存消耗似乎每天都在少量增加,而且从未下降到以前的水平。(我认为到那时那些与任务相关的资源应该已经释放了)从长远来看,这可能会导致崩溃问题。@erdem分析内存,并查找您希望符合收集条件但不符合收集条件的对象。我使用了一些分析程序,但找不到解决问题的方法。我想知道的是,我所遇到的情况(每天内存使用量少量增加)是否表示内存泄漏,或者可能与由于clr内部原因,即使在很长一段时间后(在我的情况下是几天)仍没有释放任务有关。我是否应该考虑一些明确的任务来释放任务。您确信您的<代码>作业>(执行)(< /代码>)可以处理多线程方案吗?
for (int j = 0; j < 3; j++)
{
    for (int i = 0; i < 15; i++)
    {
        var job = new BIJob(reportData);
        job.Execute();
    }
    Thread.Sleep(10000);
}
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);
}