3

我有一个简单的 ConsoleProgram,它正在创建一个包含 80 个 IDisposable 对象的列表。该对象包含两个System.Threading.ManualResetEvent在方法中关闭的对象Dispose()。请考虑代码:

public class Program
{
    private static void Main(string[] args)
    {
        Console.ReadLine();
        Test(80);
        Console.WriteLine("end.");
        Console.ReadLine();
    }

    private static void Test(int c)
    {
        Console.WriteLine("Test start.");

        List<TestObject> list = new List<TestObject>();

        for (int i = 0; i < c; i++)
            list.Add(new TestObject());

        Console.WriteLine("End of adding. Added: {0} items.", c);
        Console.ReadLine();

        foreach (TestObject obj in list)
            obj.Dispose();

        list = null;
        Console.WriteLine("Dispose end.");
    }

    public class TestObject : IDisposable
    {
        public ManualResetEvent mr1 = new ManualResetEvent(true);
        public ManualResetEvent mr2 = new ManualResetEvent(false);

        public void Dispose()
        {
            mr1.Close();
            mr2.Close();
        }
    }
}

我已经测试了我的程序以防内存消耗和内存泄漏。我认为创建所有列表对象后消耗的内存会增加,但调用Dispose()方法并将null值设置为列表对象后会减少。不幸的是,我有观察者不同的行为。请考虑以下我的测试结果:

  1. 程序启动(未创建任何内容)。工作集 = 6.700K
  2. 创建了 80 个对象的列表。WorkingSet = 7.160K(内存增长:460K)
  3. 程序将该Dispose()方法称为集合null以列出对象。WorkingSet = 7.164K(内存从最后一点增长:4K)
  4. 程序挂起超过 20 分钟。WorkingSet = 7.296K(内存从最后一点增长:105K,内存从头增长:596K)
  5. 程序已关闭。

我真的对第3点和第4点感到困惑。为什么没有释放内存?我认为这是内存泄漏,因为总内存增长等于 596K,并且从未释放。

非常感谢您的任何回答。

PS。更改对象的数量(例如更改为 9000)会导致内存增长超过 2MB。

PS2。在我的程序结束时,我要求GC.Collect()强制清理。但是在使用的内存量仍然相同并且没有减少之后 - 我很困惑。

4

1 回答 1

5

调用Dispose()并将值设置为 null 不会立即释放内存。当垃圾收集器下一次运行时,你的内存应该被释放,但这一次不是确定性的。通常,当应用程序处于内存压力下时会发生这种情况,通常是由于创建对象需要更多内存。如果没有这种压力,并且应用程序处于空闲状态,GC 可能永远不会收集您的内存。

简而言之,这不是内存泄漏。

于 2012-08-08T09:34:25.143 回答