MSDN Magazine - December 2007 - (Page 24) { // Forward progress List copy = new List (list); // expensive copy operation copy.Add(); copy.Sort(); // Expose the results list = copy; } Here,we can use the real List ,but be sure to note that we take a significant performance hit by copying the data.Additionally,using a ref parameter here isn’t really a preferable solution.However, a strong reliability contract saying“will not corrupt state”is often highly desirable. Another technique is to try to make forward progress and provide backout code in case of a failure. This is similar to constructing a transaction around your changes and providing code to roll back the changes made in the transaction. a host’s escalation policy, or for client applications, recycling the entire application. That said, CERs are truly required in places that manipulate machine or process-wide state,such as a shared memory segment. And in these cases, business needs often require that these applications are written to recover from power failures anywhere in the code, so you not only have to write CERs, but you also have to be very careful about consistency throughout significant parts of the application. This complexity is why you don’t want your summer intern writing control software for a nuclear power plant. SafeHandle You might be wondering whether you can safely return values from a method in the presence of asynchronous exceptions. You cannot safely do this! When you call an unhardened P/Invoke method like CreateFile that returns an IntPtr and then assign the return value to a local variable, two distinct machine instructions are generated, and threads can be aborted between any two machine instructions.In situations like this,using IntPtr to represent OS handles is fundamentally unreliable. But there is a solution. When you access an OS resource, such as a file, socket, or event, you get a handle for that resource, and that resource must eventually be freed.SafeHandle ensures that if you can allocate a resource, you can free that resource. To provide this guarantee, SafeHandle aggregates multiple CLR features. You define a subclass of SafeHandle and provide an implementation of the ReleaseHandle method. This method is a CER, called from SafeHandle’s critical finalizer. Assuming that your ReleaseHandle method obeys all the CER rules,you are guaranteed that if you can successfully allocate an instance of a native resource, your ReleaseHandle method will get a chance to run. SafeHandle also offers some key security features. It prevents handle recycling attacks by ensuring that no thread can free a handle while another thread is actively using it. It also prevents a subtle race condition between a class using a handle and its own finalizer.SafeHandle is also integrated with the P/Invoke marshaling layer. For any method that returns or consumes a handle, you can replace that handle with a subclass of SafeHandle. CreateFile for example, would return a SafeFileHandle, and WriteFile would take a SafeFileHandle as its first parameter. When to Use a Strong Reliability Contract The previous examples show that a strong reliability contract is difficult to implement efficiently. Using CERs is like rocket science, since you need to be prepared for failures that can occur anywhere.Note that for CERs exposed as an annotated try/finally block,the try block is not a CER,so even multiple assignment operations may be interrupted by an async exception. For this reason, CERs are not for most people—better choices are to rely on Using Locks Locks must be taken on the right types of objects.Consider the C# lock keyword,which expands into calling Monitor.Enter(Object), followed in a finally block by Monitor.Exit(Object).Locks should have a strong sense of identity—unboxed value types do not fit the bill, as they would get boxed each time you pass them as an Object. But the CLR also shares certain types across AppDomain boundaries in certain cases.Taking locks on Strings,Type objects, CultureInfo instances,and byte[]’s may end up taking a lock across AppDomain boundaries. Similarly, taking locks on any subclass of a MarshalByRefObject from outside of that class’s implementation may lock on a transparent proxy instead of the real object in the correct appdomain, meaning you might not take the right 24 msdnmagazine CLR Inside Out http://www.windowscontrols.com
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.