簡體   English   中英

線程內存泄漏

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM