托管资源与非托管资源
托管资源:由CLR管理分配和释放的资源,即由CLR里new出来的对象;
非托管资源:不受CLR管理的对象,windows内核对象,如文件、数据库连接、套接字、COM对象等;
对于应用创建的大多数对象,可以依赖 .NET Framework 的垃圾回收器来处理内存管理。 但是,如果创建包括非托管资源的对象,则当你在应用中使用完非托管资源后,必须显式释放这些资源。 最常用的非托管资源类型是包装操作系统资源的对象,如文件、窗口、网络连接或数据库连接。 虽然垃圾回收器可以跟踪封装非托管资源的对象的生存期,但无法了解如何发布并清理这些非托管资源
/// <summary>
/// 必须,以备程序员忘记了显式调用Dispose方法
/// </summary>
~SampleClass()
{
//必须为false
Dispose(false);
}
这个方法叫做类型的终结器。提供终结器的全部意义在于:我们不能奢望类型的调用者肯定会主动调用Dispose方法,基于终结器会被垃圾回收器调用这个特点,终结器被用做资源释放的补救措施。
//通知垃圾回收机制不再调用终结器(析构器)
GC.SuppressFinalize(this);
该析构函数隐式地对对象的基类调用 Finalize。这样,前面的析构函数代码被隐式地转换为:
protected override void Finalize() { try { // cleanup statements... } finally { base.Finalize(); } }
using System; using System.ComponentModel; using System.Runtime.InteropServices; public class ConsoleMonitor : IDisposable { const int STD_INPUT_HANDLE = -10; const int STD_OUTPUT_HANDLE = -11; const int STD_ERROR_HANDLE = -12; [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr GetStdHandle(int nStdHandle); [DllImport("kernel32.dll", SetLastError = true)] static extern bool WriteConsole(IntPtr hConsoleOutput, string lpBuffer, uint nNumberOfCharsToWrite, out uint lpNumberOfCharsWritten, IntPtr lpReserved); [DllImport("kernel32.dll", SetLastError = true)] static extern bool CloseHandle(IntPtr handle); private bool disposed = false; private IntPtr handle; private Component component; public ConsoleMonitor() { handle = GetStdHandle(STD_OUTPUT_HANDLE); if (handle == IntPtr.Zero) throw new InvalidOperationException("A console handle is not available."); component = new Component(); string output = "The ConsoleMonitor class constructor.\n"; uint written = 0; WriteConsole(handle, output, (uint) output.Length, out written, IntPtr.Zero); } // The destructor calls Object.Finalize. ~ConsoleMonitor() { if (handle != IntPtr.Zero) { string output = "The ConsoleMonitor finalizer.\n"; uint written = 0; WriteConsole(handle, output, (uint) output.Length, out written, IntPtr.Zero); } else { Console.Error.WriteLine("Object finalization."); } // Call Dispose with disposing = false. Dispose(false); } public void Write() { string output = "The Write method.\n"; uint written = 0; WriteConsole(handle, output, (uint) output.Length, out written, IntPtr.Zero); } public void Dispose() { string output = "The Dispose method.\n"; uint written = 0; WriteConsole(handle, output, (uint) output.Length, out written, IntPtr.Zero); Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { string output = String.Format("The Dispose({0}) method.\n", disposing); uint written = 0; WriteConsole(handle, output, (uint) output.Length, out written, IntPtr.Zero); // Execute if resources have not already been disposed. if (! disposed) { // If the call is from Dispose, free managed resources. if (disposing) { Console.Error.WriteLine("Disposing of managed resources."); if (component != null) component.Dispose(); } // Free unmanaged resources. output = "Disposing of unmanaged resources."; WriteConsole(handle, output, (uint) output.Length, out written, IntPtr.Zero); if (handle != IntPtr.Zero) { if (! CloseHandle(handle)) Console.Error.WriteLine("Handle cannot be closed."); } } disposed = true; } } public class Example { public static void Main() { Console.WriteLine("ConsoleMonitor instance...."); ConsoleMonitor monitor = new ConsoleMonitor(); monitor.Write(); monitor.Dispose(); } }
对于应用创建的大多数对象,可以依赖 .NET Framework 的垃圾回收器来处理内存管理。
但是,如果创建包括非托管资源的对象,则当你在应用中使用完非托管资源后,必须显式释放这些资源。
最常用的非托管资源类型是包装操作系统资源的对象,如文件、窗口、网络连接或数据库连接。
虽然垃圾回收器可以跟踪封装非托管资源的对象的生存期,但无法了解如何发布并清理这些非托管资源