如何分配和释放内存?

时间:2019-03-23 12:02:35

标签: .net memory garbage-collection clr idisposable

我正在使用IDisposable接口和GC,有些东西我无法理解。

所以我们有以下课程:

public class DatabaseState : IDisposable
{
    protected SqlConnection _connection;

    public virtual string GetDate()
    {
        if (_disposed)
            throw new ObjectDisposedException("DatabaseState");

        if (_connection == null)
        {
            var connectionString = ConfigurationManager.ConnectionStrings["master"];
            _connection = new SqlConnection(connectionString.ConnectionString);
            _connection.Open();
        }
        using (var command = _connection.CreateCommand())
        {
            command.CommandText = "SELECT getdate()";
            return command.ExecuteScalar().ToString();
        }
    }

    private bool _disposed;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            if (_connection != null)
            {
                _connection.Dispose();
                _connection = null;
            }
            _disposed = true;
        }
    }
}

您可以看到该类非常简单(仅获取当前日期)。

在Main中,我有以下代码:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("'g' to Get Date; 'gc' to Garbage Collect; 'x' to Exit");
        var command = "";
        while (command != "x")
        {
            command = Console.ReadLine();
            switch (command)
            {
                case "g":
                    GetDate();
                    break;

                case "gc":
                    GC.Collect();
                    break;
            }
        }
    }

    private static void GetDate()
    {
        using (var databaseState = new DatabaseState())
        //var databaseState = new DatabaseState();
        {
            Console.WriteLine(databaseState.GetDate());
        }
    }
}

第一个实验是当我使用IDisposable和(我在诊断工具中使用VS build。)

查看以下快照:

Spanshots

数字代表快照ID。

  1. 当我开始申请时。如您所见,我们仅分配了29.38 KB。
  2. 当我输入“ g”时,我们已经分配了245.70KB,这是正常的。我们已经打开了连接,握手等。
  3. 当我第二次输入“ g”时,我们仅分配了0.55 KB,这也应该是正常的。我检查了我们创建的哪种对象类型:Hashtable,Microsoft.Win32.SafeHandles.SafeFileMappingHandle,SectionRecord等。我不熟悉这些对象类型,并且我认为与CLR相关。

从现在开始,奇怪的事情发生在我身上。

4、5、6、7我也按了“ g”。如您所见,我们尚未分配任何内存。这是我的第一个问题,为什么?

  1. 我按下了“ gc”,这强制了GC.Collect()。那时我很惊讶。我们尚未释放任何记忆。据我所知,GC.Collect()释放了各代人的记忆。第二个问题为什么此时GC尚未释放任何内存?

  2. 我再次按下“ g”。与快照4、5、6和7中的情况相同。我们尚未分配任何内存。 为什么?

10、11个随机创建的快照。

  1. 这也很有趣。我尚未执行任何操作,某些内容已分配了2.4 KB内存。我再次检查了我们创建的对象类型:ContextCallback,Microsoft.Win32.SafeHandles.SafeFileMappingHandle,AppDomainPauseManager,ThreadPoolWorkQueue。同样,我不熟悉这些类型,但我认为它们与CLR有关。

  2. 与12相同。我已经有一段时间没有执行任何操作了,但是这次我们释放了20.66 KB的内存。 为什么?


总结:

据我了解,IDisposable和GC应该以一些不同的方式工作。 第一次实例化DatabaseState时,我应该打开连接,握手等。因此,我们将分配更多的内存。 由于我们在using语句中使用DatabaseState实例,因此我们将释放这些非托管资源。下次当我使用DatabaseState实例时,我应该为该实例分配一些内存(但是从快照4,5、6、7和9中我没有分配任何内存)仅为该实例分配,因为连接,握手已经完成了。

我丢失了一些东西,但是我不知道在哪里和什么地方。

致谢

0 个答案:

没有答案