About the recycling of unmanaged resources and about the recycling of managed resources
There are two ways to release unmanaged Resources
1. destructor
2. Implement the System. IDisposable Interface
I. destructor
The constructor can specify certain operations that must be performed when the class instance is created. When the Garbage Collector deletes an object, it can also call the destructor. At the beginning of the destructor, it seems that it is the best place to place the code for releasing unhosted resources and executing general cleanup operations. However, it is not that simple. The running rules of the garbage collector determine that the code to run at a certain time cannot be placed in the destructor. If the object occupies valuable and important resources, release these resources as quickly as possible, so you cannot wait for the garbage collector to release them.
Instance
C # code Replication
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MemRelease
{
class Program {
~Program() {
// Orders.
}
static void Main(string[] args) {
}
}
}
In il dasm, you will find that there is no such structure method. C # When the compiler compiles the destructor, it implicitly compiles the Destructor code into the corresponding code of the Finalize () method to ensure that the Finalize () of the parent class is executed () method:
C # code Replication
.method family hidebysig virtual instance void
Finalize() cil managed
{
// Code size 14 (0xe)
.maxstack 1
.try {
IL_0000: nop
IL_0001: nop
IL_0002: leave.s IL_000c
} // end .try
finally {
IL_0004: ldarg.0
IL_0005: call instance void [mscorlib]System.Object::Finalize()
IL_000a: nop
IL_000b: endfinally
} // end handler
IL_000c: nop
IL_000d: ret
} // end of method Program::Finalize
Several problems with using destructor to release resources:
1. Compared with C ++ destructor, the problem with C # destructor is their uncertainty. When a C ++ object is deleted, its destructor will be executed immediately. However, due to the working method of the garbage collector, it cannot be determined when the destructor of the C # object will be executed.
2. The execution of the C # destructor delays the time when the object is finally deleted from the memory. Objects with destructor need to be processed twice before they can be deleted: objects are not deleted when you call the Destructor for the first time.
Ii. IDisposable Interface
The IDisposable interface defines a pattern that provides a definite mechanism for releasing unhosted resources and avoids problems inherent in the garbage function generator. The IDisposable interface declares a method Dispose (), which does not contain parameters and returns void.
1. MSDN recommends implementing the IDisposable interface in the following mode.
C # code Replication
public class Foo: IDisposable
public class Foo: IDisposable
{
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (!m_disposed) {
if (disposing) {
// Release managed resources
}
// Release unmanaged resources
m_disposed = true;
}
}
~Foo() {
Dispose(false);
}
private bool m_disposed;
}
In the. NET object, there are actually two functions used to release resources: Dispose and Finalize.
(1) Finalize is used to release unmanaged resources, while Dispose is used to release all resources, including hosted and unmanaged
(2) void Dispose (bool disposing) function uses a disposing parameter to identify whether the current call is called by Dispose ().
If it is called by Dispose (), you need to release both hosted and unmanaged resources. If it is ~ Foo () (that is, the Finalize () of C #) is called, you only need to release the unmanaged resources.
(3) The Dispose () function is explicitly called by other code and requires resource release, while Finalize is called by GC.
Other Managed Objects referenced by Foo during GC calls may not need to be destroyed, and GC calls the objects even if they are to be destroyed. Therefore, you only need to release unmanaged resources in Finalize. On the other hand, because managed and unmanaged resources have been released in Dispose (), it is unnecessary to call Finalize again when the object is recycled by GC. Therefore, in Dispose (). suppressFinalize (this) prevents repeated calls to Finalize.
However, even if you call Finalize and Dispose repeatedly, the resource is released only once because of the existence of the variable m_disposed. Excessive calls are ignored.
Finalize and Dispose are guaranteed.
(1) Finalize only releases unmanaged resources;
(2) Dispose releases managed and unmanaged resources;
(3) It is no problem to repeatedly call Finalize and Dispose;
(4) Finalize and Dispose share the same resource release policies, so there is no conflict between them.
2. IDisposable example
C # code Replication
Reclaim namespace Resources
namespace resource recycling
{
class Program
{
static void Main (string [] args)
{
// Use using to implement IDisposable for resource management
/ * When you get an object, first determine whether the object implements the IDisposable interface. If it is implemented, it is best to wrap the object with using to ensure that the object is released after it is used up, otherwise resource leakage is likely to occur. problem
* /
using (Telphone t1 = new Telphone ())
{
t1.Open ();
t1.Speak ("hello");
t1.Bomb ();
//t1.Dispose();//If the Dispose () method is called here to release resources, then an error will occur when the t1.Open () method is executed, and the phone line has been cut, and no more calls
t1.Open ();
t1.Speak ("I am back!");
} // After the code is executed here, the Dispose method will be called to recycle the resources
Console.ReadKey ();
}
}
/// <summary>
/// Telphone class implements IDisposable interface
/// </ summary>
class Telphone: IDisposable
{
/// <summary>
/// phone status
/// </ summary>
private TelphoneState state;
/// <summary>
/// call
/// </ summary>
public void Open ()
{
if (state == TelphoneState.Disposed)
{
throw new Exception ("The phone line has been cut and cannot be opened!");
}
state = TelphoneState.Open;
Console.WriteLine ("Pick up the phone");
}
/// <summary>
/// speak
/// </ summary>
/// <param name = "s"> What to say </ param>
public void Speak (string s)
{
if (state! = TelphoneState.Open)
{
throw new Exception ("No connection");
}
Console.WriteLine (s);
}
/// <summary>
/// hang up the phone
/// </ summary>
public void Bomb ()
{
state = TelphoneState.Close;
Console.WriteLine ("Hang up the phone");
}
#region IDisposable members
/// <summary>
/// Implement the Dispose () method in the IDisposable interface to release unmanaged resources
/// How to release unmanaged resources is determined by the program itself
/// </ summary>
public void Dispose ()
{
if (state == TelphoneState.Open)
{
Bomb (); // Hang up
}
state = TelphoneState.Disposed;
Console.WriteLine ("Cut the phone line");
}
#endregion
}
/// <summary>
/// phone status enumeration
/// </ summary>
enum TelphoneState
{
Open, Close, Disposed
}
}
Program running result:
Iii. Example of mixed calls of destructor and IDisposable
C # code Replication
public class ResourceHolder: IDisposable
{
private bool isDispose = false;
// Display the called Dispose method
Public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
}
// The actual removal method
Protected virtual void Dispose (bool disposing)
{
if (! isDisposed)
{
If (disposing)
{
// This operation is performed to clear the managed object.
}
// Perform the operation of clearing unmanaged objects here
}
IsDisposed = true;
}
// destructor
~ ResourceHolder ()
{
Dispose (false);
}
}
How to host resources and how to manage unmanaged resources can be explained in the basic concept?
Managed resources and unmanaged resources should be recycled from the memory. The first point is very clear: managed resources,. net garbage recyclers are automatically recycled, unmanaged resources, and the garbage payback period cannot be automatically recycled;
In addition, managed resources are created by the. net core. Unmanaged resources are created by the. net core by calling other interfaces, which cannot be controlled by. net, such as active controls, brushes, and image brushes. These are all created by. Net calling system interfaces, which cannot be managed and can only be released by users themselves.
Finally, the. Net kernel is encapsulated. The resources that can or have the permission to automatically release are managed resources. If. Net calls external resources, the resources that cannot be automatically released are unmanaged resources.
C # Can I recycle unmanaged resources like this?
Timer is a hosted object. The Dispsoe method can be called manually, but the better method is to use the using block to call it. This can avoid the execution of the dipose due to exceptions.
For a COM Object, call Marshal. ReleaseComObject (comobj) in dispose to ensure that the COM object is correctly recycled.