Memory management in .NET usually is considered to be GARBAGE COLLETION, the programmer is not too worrying. Indeed, GC makes us (programmers) through the management of managed heap, which will focus on the logic of the program from a cumbersome to liberate from a cumbersome problem such as memory leak. However, all things are handed over to GC Sometimes the efficiency of the program will be damaged, and it may even result in errors. This is because GC can effectively manage managed objects, but for those non-hosting resources (such as file handles, Socket links, etc.) or require special care (such as Bitmap objects, etc.), GC performance is not It is so good. For these work, GC requires programmers' assistance to complete it. Therefore, it is important to use GC to perform memory management, which is important in .NET. This is also one of the directions that should be considered when optimizing the .NET program.
GARBAGE COLLECTION
There are many very good articles about the discussion of GC principles. I remember "programmer" in the first phase of 2003, I also specially made a topic of GC, including the article of "Garbage Collection - Problem and Technology". Therefore, this article does not intend to do too much discussion on the principles of GC. If you have doubts in this, you can refer to this article.
Simply put, the garbage collector used by .NET CLR is a typical independent, marker-and-introc collector. It divides the entire hosted pile into several (default is 3) Generation, using the mark-and-clean algorithm for garbage collection, and then organizes the hosted heap, and the non-spam is compressed. To reduce memory debris.
In order to improve the algorithm efficiency, .NET CLR implements two types of GC: workstation GC (Mscorwks.dll) and server GC (MSCORSVR.DLL). When running (run-time) is loaded into the process, which GC can be selected via the CORBINDTORUNTIMEEX () function. The server GC is designed specifically for a server system with a multiprocessor. It uses a parallel algorithm, each CPU has a GC, and the program on the CPU will be suspended when the GC process is performed. Such a design is capable of improving the data throughput of the server as much as possible. All single-processor systems work in workstation GC mode, the workstation GC does not exist in parallel mode, and its design goal is to minimize the number of procedures suspended during garbage collection. Obviously, if the workstation GC is used in the multiprocessor system, it will undoubtedly reduce the performance of the system and the powerful power of the multiprocessor cannot be played. Therefore, select the appropriate GC to make effective memory management first.
Dispose () vs. finalize ()
For those non-hosting resources mentioned above, it is usually necessary to do some appropriate cleanup work before release. .NET provides two ways to perform these cleanup works in two ways to deliver Dispose () and Finalize (). So what is the difference between these two ways? Simply put, Dispose () is provided to the programmer call; and Finalize () is to let GC call. See the table below for the specific difference:
DISPOSE () and Finalize () main difference
Dispose ()
Finalize ()
Who is called?
Programmer GC
When is it called?
Decided by the programmer
unpredictable
What kind of order is called?
Decided by the programmer
unpredictable
When is resources released?
After the call is over
After the next GC process, the object is still available before.
The reason why it is different because the GC does not recover it directly when an object with Finalizer (Finalize () method) can be recycled, but a reference to it to a special queue . A separate thread traversed this queue, call the Finalize () method of each element in the queue one by one. Finalize () method The object being called will be released in the next GC process. Programmers have no right to control this thread and cannot access this queue. And Dispose () is part of the IDisposable interface, which is specifically used to achieve the cleaning of objects.
Based on the above difference, we have four strategies to achieve object clearance.
1, simultaneous DISPOSE () and Finalize ().
This method is recommended for .NET recommended for objects with managed resources and unmanaged resources. Implementing the Dispose () method allows the programmer to release it immediately when a known resource is no longer used. However, due to Dispose () forced programmers must do the displayed calls to release resources, implement Finalize () ensures that resources can be released correctly when Dispose () is not called.
Typical implementation patterns are as follows:
Public Class Sample: IDisposable
{
//Mplement idisposable.
Public void dispose ()
{
Dispose (TRUE);
// forbid gc to call finalizer.
Gc.suppressFinalizer (this);
}
Protected Virtual Void Dispose (BOOL Disposing)
{
IF (Disposing)
{
// Free management Objects.
}
// free unmanaged Objects, and set large fields to null.
}
// finalizer.
~ Sample ()
{
Dispose (false);
}
}
In C # and Managed C , use the destructor to implement the femalize () method. The destructor can automatically generate the femalize () method, and generate calls for the base class finalize () method [1].
2, only the Dispose () method.
This applies to only objects that only host the resource. If you want to provide a clear opportunity to release resources for such objects, this way can be used. Typical implementation patterns are as follows:
Public Class Sample: IDisposable
{
//Mplement idisposable.
Public Virtual Void Dispose ()
{
// Free management Objects.
}
}
3, only Finalize ().
This approach is not recommended, which is only suitable for programmers to unable to determine when the resources can be released, or the resources used are complex to unable to be released by display, and can only be forced to recover by Finalize (). These two situations should not appear in a well-designed project, if you have to use this way, then you should first check your design.
The implementation code is as follows:
Public Class Sample
{
//Mplement idisposable.
~ Sample ()
{
}
}
4, neither dispose () or Finalize () is not implemented.
This approach is suitable for only the objects that contain only references to other managed objects, which neither need Dispose, nor of Finalize.
Summary When using Dispose () and finalize () to assist GC to efficient memory management, the following rules should be followed:
· The object should be released immediately (set to null, or call it).
· For objects that use the non-hosting resources, the Dispose () and Finalize () methods should be simultaneously implemented to clean up.
· It should be prohibited from calling objects that have been Dispose, "Re-create objects that have been Dispose" is difficult to implement (.NET Framework is powerful).
· It should be guaranteed that dispose () will not throw an exception twice.
• When Finalize () must be implemented, the IDisposable interface should be implemented (also the Dispose () method).
· Use Finalize () only if you have to use it, or if you have to use it.
[1]: This is incorrect here, thank you for the netizen Zhangdawei78 to point out J