开发者

Why finalizer is always called?

I ran the following code and found that finalizer is always called. But many articles said that finalizer is non-desterministic.

class Test
{
    Test()
    {
        throw new Exception();
    }

    ~Test()
    {开发者_如何学C
        Console.WriteLine("Finalizer is called");
    }

    static void Main()
    {
        try
        {
            new Test();
        }
        catch { }
    }


It is still non-deterministic in your case. Non-deterministic means the amount of time it takes for something to happen cannot be pre-calculated. Note that being unable to correctly determine when something will happen does not necessarily mean random-time but in most cases they are roughly the same.

People who never have to control car brakes, industrial robots or the space shuttle generally should not care weather a piece of code is deterministic or not.

note: I have written code to control industrial robots so I sometimes need to care about my code being executed at the exact moment I want it to be.


The garbage collector calls the finalizer when it collects the object. You can suppress the finalizer call by calling GC.SuppressFinalize(); Documentation

You could place this call inside Dispose() to stop the garbage collector from collecting the class after its resources have been disposed.


In your case, the finalizer is running as part of application shutdown. From the docs:

During shutdown of an application domain, Finalize is automatically called on objects that are not exempt from finalization, even those that are still accessible.

Non-deterministic refers to when Finalize will be called. But except in exceptional cases (like power being cut off or the process being abruptly killed), the finalizer will eventually be called.


There are cases when it may not be called; and cases where even if it is called, it may not be allowed to complete.


While there are certain occasions when the finalizer will not be called, it will typically be called. The big issue is when it is called, hence it is non-deterministic.

C# is garbage-collected and the garbage collector runs at unspecified intervals. Therefore, if the finalizer needs to do something time-sensitive, it is best to use Dispose instead of a finalizer. For example, you might want to close a database connection immediately instead of leaving it open while waiting for the garbage collector.


That code is so simple that the .NET Runtime can run the finalizer with out problems but in high load applications the Finalizers are only called when garbage collection runs.

There is here an extract of this article

http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

Finalization

The garbage collector offers an additional feature that you may want to take advantage of: finalization. Finalization allows a resource to gracefully clean up after itself when it is being collected. By using finalization, a resource representing a file or network connection is able to clean itself up properly when the garbage collector decides to free the resource's memory.

Here is an oversimplification of what happens: when the garbage collector detects that an object is garbage, the garbage collector calls the object's Finalize method (if it exists) and then the object's memory is reclaimed. For example, let's say you have the following type (in C#):

public class BaseObj {
    BaseObj() {}

    protected override void Finalize() {
        // Perform resource cleanup code here... 
        // Example: Close file/Close network connection
        Console.WriteLine("In Finalize."); 
    }
}

Now you can create an instance of this object by calling:

BaseObj bo = new BaseObj();

Some time in the future, the garbage collector will determine that this object is garbage. When that happens, the garbage collector will see that the type has a Finalize method and will call the method, causing "In Finalize" to appear in the console window and reclaiming the memory block used by this object.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜