C#BackgroundWorker在重新启动时消耗内存

C#BackgroundWorker在重新启动时消耗内存,c#,multithreading,winforms,backgroundworker,C#,Multithreading,Winforms,Backgroundworker,我用以下代码创建了一个空表单,以测试连续重新启动后台工作程序的性能 public Form1() { InitializeComponent(); BackgroundWorker bw = new BackgroundWorker(); // Do work on Background thread bw.DoWork += DoWork_WorkerThread;

我用以下代码创建了一个空表单,以测试连续重新启动后台工作程序的性能

        public Form1()
        {
            InitializeComponent();

            BackgroundWorker bw = new BackgroundWorker();
            // Do work on Background thread
            bw.DoWork += DoWork_WorkerThread;
            bw.RunWorkerAsync();
            // Return to UI thread and Restart the worker
            bw.RunWorkerCompleted += DoWork_WorkerThreadCompleted;
        }

        private void DoWork_WorkerThread(object sender, DoWorkEventArgs e)
        {
            System.Threading.Thread.Sleep(100);
            //GC.Collect();
        }

        private void DoWork_WorkerThreadCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // Restart the worker.
            // We can verify its the background worker because commenting this out relieves the issue.
            ((BackgroundWorker)sender).RunWorkerAsync();
        }
您可以看到,在任务管理器中,每当工作线程从
DoWork\u WorkerThreadCompleted
重新启动时,内存就会跳起来

我注意到,如果我在工作线程中加入一个
GC.Collect()
,问题就会消失。我是否错误地重新启动了工作线程,或者是否有办法确保在不调用
GC.Collect()
的情况下释放后台线程


感谢您的时间。

只有少数用例需要显式调用GC。重复某个操作时内存增加并不一定意味着内存泄漏。NET for one只在真正需要时释放内存,比如内存压力很大时。调用
GC.Collect
只会强制执行问题

评论工人的开始并不能真正证明什么。虽然在这种情况下您已经阻止了内存的增加,但您也消除了在工作进程运行到完成时释放内存的可能性,并为再次释放内存留出了足够的时间或事件你永远无法准确预测GC何时会发生。调用
GC.Collect
无法承受

你可以用另一种方式来思考这个问题。想象一下,分配一个您知道使用了合理数量RAM的对象

void DoSomething()
{
    var ob = new MyObjectRequiringReasonableAmountOfRam();
    // 'ob' goes out of scope and is now a candidate for GC at some time or other
}
现在调用此方法时,对象被分配并超出范围,是的,内存可能会增加,但认为内存泄漏还为时过早。当然,注释掉代码会消除“泄漏”的症状,但它也会像注释掉工作线程一样删除功能

现在,如果除了调用上述方法,我还调用:

void DoSomethingSlightlyMoreDrastic()
{
    var ob = new MyObjectRequiringALargerAmountOfRam();
    // 'ob' goes out of scope and is now a candidate for GC at some time or other
}

..NET看到此分配需要更多内存,并考虑系统上的所有其他因素,例如进程分配了多少内存;来自所有其他进程的内存;您的计算机中的RAM以及GC如何工作的规则,此时完全有可能您的第一个对象得到GC。

您是否知道GC没有在
IDisposable
对象上调用
.Dispose()
?旁注:您可能应该在调用RunWorkerAsync之前分配RunWorkerCompleted事件。另外,启动一个线程会消耗至少1MB的RAM,因为它会创建一个运行时堆栈和其他东西。感谢各位对已完成事件的回复和良好调用。谢谢你的解释。在这个场景中,我不应该看到垃圾回收器开始工作,并平级或降低内存使用率吗?在这个例子中,似乎增加了constant@clamchoda不客气。也许它正在启动,而你却不知道?在调试器中运行它,并确保“诊断工具”窗口处于打开状态。GC事件通常以黄色显示。