[英]C# BackgroundWorker eats memory on restart
我使用以下代碼創建了一個空的Form,以測試連續重啟后台工作程序的性能;
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_WorkerThreadCompleted
重新啟動工作程序時,在任務管理器中,內存都會跳躍。
我注意到,如果我將GC.Collect()
放入工作線程中,問題就消失了。 我是不正確地重新啟動工作線程,還是有辦法確保無需調用GC.Collect()
即可處置后台線程?
謝謝你的時間。
只有少數幾個用例需要顯式調用GC。 僅僅因為在重復操作時內存增加,並不一定意味着內存泄漏。 .NET for僅在真正需要時才釋放內存,例如內存壓力很高時。 調用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。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.