[英]Thread memory leak
我試圖在更大的C#程序中追蹤內存泄漏,該程序產生多個線程。 在這個過程中,我創建了一個小方程序,我用它來測試一些基本的東西,我發現了一些我真的不明白的行為。
class Program
{
static void test()
{
}
static void Main(string[] args)
{
while (true)
{
Thread test_thread = new Thread(() => test());
test_thread.Start();
Thread.Sleep(20);
}
}
}
運行這個程序,我看到程序的內存使用量穩步增加而沒有停止。 在短短幾分鍾內,內存使用量超過100MB並繼續攀升。 如果我注釋掉test_thread.Start();行,那么程序使用的內存最大可以達到幾兆字節,並且會升級。 我還嘗試使用GC.Collect()在while循環結束時強制進行垃圾收集,但它似乎沒有做任何事情。
我認為一旦函數完成執行允許GC拖動它就會取消引用該線程,但這似乎並沒有發生。 我不能在這里深入理解更深層次的東西,我將非常感謝幫助解決這個問題。 提前致謝!
這是設計使然,您的測試程序應該顯示內存使用失控。 您可以從Taskmgr.exe中查看基本原因。 使用View + Select Columns並勾選“Handles”。 觀察您的過程的句柄數量是如何穩步增加的。 內存使用量隨之增加,反映了句柄對象使用的非托管內存。
設計選擇非常勇敢,CLR每個線程使用5個操作系統對象。 管道,用於同步。 這些對象本身是一次性的,設計選擇是不要使Thread類實現IDisposable。 這對.NET程序員來說非常困難,很難在正確的時間調用Dispose()。 在任務類設計中沒有表現出來的勇氣,導致大量的手工擰干和一般建議不要打擾 。
這不是通常一個精心設計的.NET程序有問題。 GC運行的頻率足以清理那些OS對象。 並且Thread對象正在謹慎創建,使用ThreadPool進行非常短的運行線程,就像測試程序使用的那樣。
它可以,我們看不到你的真實節目。 請注意從這樣的綜合測試中得出太多結論。 您可以使用Perfmon.exe查看GC統計信息,讓您了解它是否經常運行。 一個體面的.NET內存分析器是首選的武器。 GC.Collect()是備用武器。 例如:
static void Main(string[] args) {
int cnt = 0;
while (true) {
Thread test_thread = new Thread(() => test());
test_thread.Start();
if (++cnt % 256 == 0) GC.Collect();
Thread.Sleep(20);
}
}
而且你會看到它現在來回反彈,永遠不會超過4 MB。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.