20th chapter exception and state management 20.7-20.13

Source: Internet
Author: User
Tags finally block

20.7 reliability in exchange for development efficiency

Object-oriented programming, compiler functionality, CLR functionality, and a large class library make the. Net framework an attractive development platform. But all of these things will introduce in your code the "wrong point" that you have no control over, if Outofmemoryexcepton and so on. Program development is unlikely to capture these exceptions one by one, making the application absolutely robust. Unexpected exceptions often cause the state of the program to break down, in order to alleviate the damage to the state, you can do several things:

When executing a catch or finally block, the CLR does not allow the thread to be terminated, so it is possible to write to the following transfer method to become robust:

Private void  from decimal amount)        {            try {/* *  Nothing is done here * / }            finally             {                from. Money-= amount                ; // now, thread termination is not possible here (due to thread.abort/appdomain.unload)                To. Money + = amount;            }        }

However, it is never recommended to put all your code in the finally block! This technique is only suitable for modification and its sensitive data.

You can use the System.Diagnostics.Contracts.Constract class to apply a code contract to a method.

You can use the Constrained execution area (Constrained excecution region,cer), which provides a way to eliminate CLR uncertainties.

You can use transactions (transaction) to ensure that the State is either modified or not modified. such as the TransactionScope class.

Design your own method more clearly. The following monitor class implements thread synchronization:

 Public Static classSomeType {Private Static ReadOnly ObjectS_lockobject =New Object();  Public Static voidSomeMethod () {monitor.enter (s_lockobject);//If an exception is thrown, is the lock acquired? //If a lock has been acquired, it will not be released.            Try            {                //perform a thread-safe operation here            }            finally{monitor.exit (s_lockobject); }        }    }

Because of the problem shown above, this overloaded monitor's Enter method is no longer encouraged to use, it is recommended to write as follows:

 Public Static classSomeType {Private Static ReadOnly ObjectS_lockobject =New Object();  Public Static voidSomeMethod () {BOOLLockTaken =false;//Assuming no lock is acquired            Try{monitor.enter (S_lockobject,refLockTaken);//The following code works regardless of whether an exception is thrown//perform a thread-safe operation here            }            finally            {                //If you get it, release it.                if(LockTaken = =true) Monitor.Exit (s_lockobject); }        }    }

Although the above code becomes more explicit, but in the case of thread synchronization locks, it is now advisable not to use them with exception handling at all.

If the state is determined to be damaged to an extent that cannot be modified, all damaged states should be destroyed to prevent it from causing more damage. Then restart the application to restore the application to a good state. Because managed code cannot be leaked outside of an AppDomain, you can call the AppDomain 's Unload method to unload the entire AppDomain. If you feel that the state is too bad to terminate the process, you can call environment 's FailFast method. The exception message can be specified in this method, and no active try/finally block or Finalize method is run when this method is called. It then sends the message to a log of Windows application.

20.8 guiding principles and best practices

We think the finally block is very powerful! The code in the finally block is guaranteed to execute regardless of what exception the thread throws. The finally block should be used to clean up those operations that have started successfully, and then return to the caller or code after the finally block is executed. Finally blocks are also often used to display disposed objects to avoid resource leaks. The following example:

        Public Static voidSomeMethod () {FileStream fs=NewFileStream (@"C:\test.txt", FileMode.Open); Try            {                //Displays the result of dividing 100 by the first byte of a fileConsole.WriteLine ( -/FS.            ReadByte ()); }            finally            {                //cleans up resources, and files can be closed even if an exception occursFS.            Close (); }        }

It is so important to ensure that cleanup code is executed so that many programming languages provide constructs that simplify the writing of cleanup code. For example, the C # compiler automatically generates try/finally blocks whenever lock,using and foreach statements are used. In addition, the C # compiler automatically generates Try/catch blocks when overriding the class's destructor (Finalize). With these constructs, the compiler puts your written code inside the try block and automatically places the cleanup code inside the finally block, as follows:

With the lock statement, the lock is freed in the finally block.

With the using statement, the Dispose method of the object is called in the finally block.

Using the foreach statement, the Dispose method of the IEnumerator object is called in the finally block.

When you define a destructor method, the Finalize method of the base class is called in the finally block.

For example, using a using statement instead of the code above has less code, but the result is the same after compilation.

         Public Static void SomeMethod ()        {            usingnew FileStream (@ "c:\test.txt", FileMode.Open))            {                Console.WriteLine/  fs. ReadByte ());            }                 }
20.9 unhandled exceptions

When an exception is thrown, the CLR looks up in the call stack for a catch block that matches the thrown exception type.

When an exception is thrown, the CLR looks up in the call stack for a catch block that matches the exception type thrown. If a matching catch block is not found, an unhandled exception occurs. The CLR detects that any thread in the process has an unhandled exception and terminates the process. Each Microsoft application has its own approach to dealing with unhandled exceptions.

For any application, consult the System.domain UnhandledException event.

For WinForm applications, consult the System.Windows.Forms.NativeWindow onthreadexception virtual method, System.Windows.Forms.Application onthreadexception virtual method, System.Windows.Forms.Application threadexception event.

For WPF applications, consult the System.Windows.Application dispatcherunhandledexception event and the System.Windows.Threading.Dispatcher UnhandledException and UnhandledExceptionFilter events.

For Silverlight, consult the System.Windows.Forms.Application threadexception event.

For an ASP. NET application, consult the System.Web.UI.TemplateControl error event. The TemplateControl class is the base class for the System.Web.UI.Page class and the System.Web.UI.UserControl class. Also, query the System.Web.HttpApplication error event.

20.10 Debugging an exception

20.11 performance issues with exception handling 20.12 constraint execution region (CER)

The constraint execution area is a code block that must be adaptable to the error, white point, that is, this block of code to ensure that the reliability is very high, as far as possible exception. Take a look at the following code:

        Public Static voidDemo1 () {Try{Console.WriteLine ("In Try"); }            finally            {//The static constructor of the Type1 is implicitly called heretype1.m (); }        }        Private Sealed classType1 {StaticType1 () {//if this throws an exception, M will not get the callConsole.WriteLine ("Type1 ' s static ctor called."); }             Public Static voidM () {}}

Run the above code to get the following result:

In Try

Type1 ' s static ctor called.

We hope that the code in the try block will not start executing unless the code in the finally block is guaranteed to be executed. For this purpose, you can modify the code as follows:

  Public Static voidDemo1 () {//forcing finally code blocks to be prepared in advanceruntimehelpers.prepareconstrainedregions (); Try{Console.WriteLine ("In Try"); }            finally            {//The static constructor of the Type1 is implicitly called heretype1.m (); }        }        Private Sealed classType1 {StaticType1 () {//if this throws an exception, M will not get the callConsole.WriteLine ("Type1 ' s static ctor called."); }         [ReliabilityContract (Consistency.willnotcorruptstate, cer.success)] Public Static voidM () {}}

The results are as follows:

Type1 ' s static ctor called.

In Try

PrepareConstrainedRegions is a very special method, and the JIT compiler encounters this method and compiles the code in the catch and finally blocks associated with the try in advance. The JIT compiler loads any assembly, creates any type, invokes any static constructor, and JIT-compiles the method, and if any of these operations occur abnormally, the exception is thrown in the try block.

The method that requires JIT preparation must apply the ReliabilityContract attribute, and the parameters passed to this attribute must be Consistency.willnotcorruptstate or Consistency.maycorruptinstance. This is because if the method destroys the state of the AppDomain or process, the CLR will not be able to make any guarantees about the state's consistency. Make sure that only the methods that are described in the finally block have the ReliabilityContract attribute applied. Another parameter cer.success passed to ReliabilityContract, which means that the method does not fail, otherwise cer.mayfail. Cer.none This value indicates that the method does not guarantee the CER. In other words, the method does not have a CER concept. The method that does not apply the ReliabilityContract attribute is equivalent to the following

[ReliabilityContract (Consistency.maycorruptprocess, Cer.none)]

There are several static methods that force the JIT compiler to prepare beforehand, which are defined in Runtimehelper:

public static void PrepareMethod (RuntimeMethodHandle method);

public static void PrepareMethod (RuntimeMethodHandle method, runtimetypehandle[] instantiation);

public static void PrepareDelegate (Delegate D);

public static void Preparecontracteddelegate (Delegate D);

You should also focus on RuntimeHelpers's executecodewithguaranteedcleanup approach, which is another way to execute code when the resource is guaranteed to be cleaned:

public static void Executecodewithguaranteedcleanup (Runtimehelpers.trycode code, Runtimehelpers.cleanupcode Backoutcode, Object userData);

Call this method to pass the body of the try and finally blocks as callback methods whose prototypes match each of the following two delegates:

public delegate void TryCode (object userData);

public delegate void CleanupCode (object userData, bool ExceptionThrown);

Finally, another way to ensure that your code executes is to use the CriticalFinalizerObject class.

20.13 Code Contracts

Code contract provides a way to assert code design decisions directly in your code.

Pre-conditions are generally used for validation of parameters.

A post-conditional method validates the state when it terminates with a normal return or because an exception is thrown.

Object invariant is used for the entire lifetime of an object, preserving the good state of the object field.

Code contracts facilitate the use, understanding, evolution, testing, documentation, and initial error checking of code. The pre-condition, post-condition, and object invariance can be imagined as part of the method signature. As a result, the new version of the code can become more lenient, but unless backward compatibility is compromised, the new version of the code's contract cannot become more restrictive.

The core of the code contract is the static class System.Diagnostics.Contracts.Contract. Because the technology is relatively new, the actual use of the opportunity is not much, so no longer devote a lot of energy to study. Refer to MSDN documentation for details.

20th chapter exception and state management 20.7-20.13

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.