C # Programming (74)----------Releasing unmanaged Resources

Source: Internet
Author: User

Releasing unmanaged Resources

When it comes to releasing unmanaged resources, I think it is necessary to first meet the unmanaged resources, since there are unmanaged resources, there must be managed resources.

Managed resources refer to the resources that. NET can recycle from Brown, primarily the memory resources allocated on the managed heap. The recycling of managed resources is not a manual intervention, and the. NET runtime is recycled in the appropriate call to the garbage collector.

An unmanaged resource is a resource that. NET does not know how to recycle, the most common type of unmanaged resource is an object that wraps operating system resources, such as files, Windows, network Connections, database connections, brushes, icons, and so on. This type of resource, the garbage collector calls Object.Finalize () when it cleans up Method. By default, the method is empty, and for unmanaged resources, you need to write code in this method that reclaims the unmanaged resources so that the garbage collector correctly reclaims the resources.

In. NET, the Object.Finalize () method cannot be overloaded, and the compiler automatically generates the Object.Finalize () method based on the destructor of the class, so for classes that contain unmanaged resources, you can place code that frees unmanaged resources in a destructor.

Note that the managed resource cannot be freed from the destructor, because the destructor is called by the garbage collector, and the managed resources contained by the class may have been reclaimed before the destructor call, resulting in an unpredictable structure.

Originally, if the unmanaged resources could be recycled by the garbage collector as described above, the unmanaged resources are generally limited and valuable, and the garbage collector is automatically called by the CLR (not known to the CLR for my previous article), so there is no guarantee of releasing unmanaged resources at the first level. A Dispose () method is defined so that users can manually release unmanaged resources. The Dispose () method is a lightning-proof managed resource and unmanaged resource, and after the consumer calls this method manually, the garbage collection period does not reclaim the instance again. The Dispose () method is called by a consumer, and when invoked, both the managed and unmanaged resources of the class must not be reclaimed, so both resources can be reclaimed at the same time.

Microsoft has specifically defined an interface for the collection of unmanaged resources: IDisposable, which can contain only one Dispose () method. Any class that contains unmanaged resources should inherit this interface.

In a class that contains unmanaged resources, the standard practice for resource deallocation is:

(1) Inherit idisposeable interface;

(2) The matter Dispose () method, in which the managed and unmanaged resources are released and the object itself is removed from the garbage collector (the garbage collector is not reclaiming this resource);

(3) Implementing a class destructor in which to release unmanaged resources

When used, the display calls the Dispose () method to release resources in a timely manner, while improving performance by removing the execution of the Finalize () method, and if the call to Dispose () method is not displayed, the garbage collector can also release unmanaged resources through destructors. The garbage collector itself has the ability to reclaim managed resources, guaranteeing the normal release of resources, except that the garbage collector recycles the unmanaged resources that are not released in a timely manner.

In. NET, you should use as little of the destructor as possible to free up resources. Objects without destructors are removed from memory in a single processing of a garbage processor, but objects with destructors require two of times, the first time the destructor is called, and the object is deleted the second time. And the destructor contains a lot of free resource code, Reduces the work necklace of the garbage collector and affects performance. Therefore, for objects that contain unmanaged resources, it is best to call the Dispose () method in a timely manner to reclaim resources instead of relying on the garbage collector.

Above is a few of the resources in. NET for classes that contain unmanaged resources, as long as you write the code as described above, the exhaustion is a resource-safe class.

Case:

Class Myresourcewrapper:idisposable

{

public void Dispose ()

{

Console.WriteLine ("Release Resources with Dispose");

Console.beep ();

}

}

Class Program

{

static void Main (string[] args)

{

MyResourceWrapper Mr = New MyResourceWrapper ();

Mr. Dispose ();

}

}

When we show the call to the Dispose method, we can hear the system beep.

Note: It is also a potential risk for the release of the resource by the Dispose method, which needs to be displayed by the programmer, if the call to Dispose is omitted from the code or an exception is generated before the Dispose call, and no Dispose is specified. Then some of the resources may have been left in memory.

So we should use the following method to ensure that the Dispose method can be called to:

static void Main (string[] args)

{

MyResourceWrapper Mr = New MyResourceWrapper ();

Try

{

Do something wiht Mr Object

}

Finally

{

Mr. Dispose ();

}

}

However, every time you write a idspose code that is cumbersome to use a try block, fortunately in C #, we can reuse the using keyword to simplify the call to dispose.

Reusing using keywords

In C #, the using statement provides an efficient way to call the object Dispose method. For any type of IDisposable interface, you can use the using statement, and for those types that do not implement the IDisposable interface, Using a USE statement can result in a compilation error.

static void Main (string[] args)

{

using (MyResourceWrapper Mr = New MyResourceWrapper ())

{

Do something with Mr Object

}

}

At the end of the using statement block, the Dispose method of the Mr Instance is called automatically, and the using statement not only exempts the programmer from entering the code for the Dispose call, but also guarantees that the Dispose method is invoked, regardless of whether the using statement block is executed successfully. In fact, the C # compiler automatically adds a try/finally statement block to the using statement.

. NET provides two ways to release unmanaged resources, one is the Finalize method and the Dispose method.

Next, we'll look at the Finalize method

In the base class System.Object of. NET, a virtual method named Finalize () is defined, and this method does nothing by default. We can override the Finalize method for a custom type, Add the necessary unmanaged resource cleanup logic to the method. When you want to delete an object of this type from the inner respect, the garbage collector invokes the object's Finalize method. So whether or not a spontaneous garbage collection is done by. NET, or by Gc.collect (), The Finalize method is always called. In addition, when the AppDomain that hosts the application is removed from memory, the Finalize method is also called.

Overriding the Finalize method

Assuming we now have a type of unmanaged resource, we need to rewrite the Finalize method to clean up the unmanaged resource, but when the Finalize method is overridden in the following way, a compilation error occurs:

Class MyResourceWrapper

{

protected override void Finalize ()

{ }

}

In fact, when we want to rewrite the Finalize method, C # provides us with (like C + +) destructor syntax (C # Finalizer) to override the method. C # Finalizer and constructor syntax are similar, the method name is the same as the type name, except that the Terminator has a ~ prefix and cannot use the access modifier, does not accept arguments, cannot be overloaded, so a class can have only one finalizer.

Class MyResourceWrapper

{

~myresourcewrapper ()

{

Console.WriteLine ("Release unmanaged Resources");

Console.beep ()//t play the Beep through the console player

}

}

The reason that C # only supports this way of rewriting the Finalize method is because the C # compiler aftertaste The Finalize method implicitly by adding some necessary base code. I won't show you any of the basic code I've added, anyway, just to make sure the Finalize method is always executed.

When we execute the following code, we can hear the beep:

MyResourceWrapper Mr = New MyResourceWrapper ();

Working mechanism of Finalize

His working mechanism is very complex, want to study in depth, you can check the Internet (no one is estimated), I just refer to some of the more simple online statements to understand the working mechanism of finalize.

In fact, the Finalize method is very resource-intensive, the role of the Finalize method is to ensure that the. NET object can clear 0 of unmanaged resources during garbage collection, if you create a type that does not use unmanaged resources, the implementation of finalizers is of no effect, so, You should avoid rewriting the Finalize method if there is no special need.

Combination of Dispose and finalize

Finalize can be called automatically by garbage collection, and dispose needs to be called by the code. So, for the sake of insurance, it is necessary to implement finalizers for some unmanaged resources (what is a finalizer, see last), that is to say, If we forget to explicitly call Dispose, then garbage collection will also call finalize, thus guaranteeing the recycling of unmanaged resources.

A good pattern is provided in msnd to implement the IDisposable interface to combine Dispose and finalize, as shown in the following example:

Class Myresourcewrapper:idisposable

{

private bool isdisposed = false;

~myresourcewrapper ()

{

Dispose (FALSE);

}

public void Dispose (bool disposing)

{

if (!this. isdisposed)

{

if (disposing)

{

Clear Managed Resources

}

Clear unmanaged Resources

}

This. Isdisposed = true;

}

public void Dispose ()

{

Dispose (TRUE);

Tell the GC not to call the Finalize method

Gc. SuppressFinalize (this);

}

}

In this mode, the void Dispose (bool disposing) function uses a disposing parameter to distinguish whether the current is being called by Dispose (). If it is called by Dispose (). If it is called by Dispose (), You need to release both managed and unmanaged resources at the same time. If it is called by the finalizer, then only the unmanaged resources need to be freed. The Dispose () function is explicitly called by other code to release resources on demand, and finalize is called by the GC.

Also, because managed and unmanaged resources have been freed in Dispose (), it is not necessary to call finalize again when the object is reclaimed by GC, so call Gc.suppressfinalize (this) in Dispose () Avoid repeating the call to finalize. Again, because the isdisposed variable exists, the resource will only be freed once, and the extra call will be ignored.

The advantages of this model are as follows:

1. If you do not explicitly call Dispose () and do not release both managed and unmanaged resources, finalize is also executed at garbage collection, freeing the unmanaged resources, and the GC frees the managed resources.

2. If Dispose () is called and the managed and unmanaged resources are released in a timely manner, the object is garbage collected without a Finalize (), which improves the efficiency of the use of unmanaged resources and improves system performance.

Finalizers (finalizer) are primarily used in C #. NET in unmanaged code cleanup, typically both finalizers and Dispose methods are implemented. This will increase the performance of garbage collection for careful users who directly display the call to Dispose method, although forgetting to call the Dispose method for careless users does not allow unmanaged resources to be freed. The code is as follows:

C # Programming (74)----------Releasing unmanaged Resources

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.