Printer Friendly Version      Send     
Click to Rate and Give Feedback
Related Articles
We introduce you to the benefits of building composite applications with the Composite Application Guidance for WPF from Microsoft patterns & practices.

By Glenn Block (September 2008)
ADO.NET Data Services provide Web-accessible endpoints that allow you to filter, sort, shape, and page data without having to build that functionality yourself.

By Shawn Wildermuth (September 2008)
See how routed events and routed commands in Windows Presentation Foundation form the basis for communication between the parts of your UI.

By Brian Noyes (September 2008)
Technology changes at a lightening-fast pace. This month Howard Dierking considers how the rapid changes affect developer priorities and magazine focus.

By Howard Dierking (September 2008)
More ...
Popular Articles
Here the author uses Document Information Panels in the Microsoft 2007 Office system to manipulate metadata from Office docs for better discovery and management.

By Ashish Ghoda (April 2008)
Performance problems can creep into your Web app as it scales up, and when they do, you need to find the causes and the best strategies to address them.

By Richard Campbell and Kent Alstad (April 2008)
If you're unfamiliar with Windows Presentation Foundation (WPF), building that first Silverlight custom control can be a daunting experience. This article walks through the process.

By Jeff Prosise (August 2008)
Kenny Kerr sings the praises of the new Visual C++ 2008 Feature Pack, which brings modern conveniences to Visual C++.

By Kenny Kerr (May 2008)
More ...
Read the Blog
SQL Server 2008 supports a new data type, HierarchyID, that helps solve some of the problems in modeling and querying hier­archical information. In the September 2008 issue of MSDN Magazine, Kent Tegels introduces you to the ...
Read more!
Many people using SharePoint technologies don't realize that there is auditing support built directly into the Windows SharePoint Services (WSS) 3.0 platform. In the September 2008 issue of MSDN Magazine, Ted Pattison walks you through a ...
Read more!
The September 2008 issue of MSDN Magazine is now available online. Here's what's in the issue: Hierarchy ID: Model ...
Read more!
Silverlight 2 features a rich and robust control model that is the basis for the controls included in the platform and for third-party control packages. You can also use this control model to build controls of your own. In the August 2008 issue of MSDN Magazine, Jeff Prosise describes how to ...
Read more!
In the August 2008 issue of MSDN Magazine, Matt Milner covers several topics regarding development with Windows Workflow Foundation, some that are intended to address specific reader questions, such as how to safely share a persistence database ...
Read more!
LINQ is a powerful tool enabling quick filtering data based on a standard query language. It can tear through a structured set of data using a simple and straightforward syntax. In the August 2008 issue of MSDN Magazine, Jared Parsons demonstrates a ...
Read more!
More ...
CLR Inside Out
Managing Object Lifetime
Tim Fischer

Although the Microsoft® .NET Framework provides a managed execution environment, it is important to use resources carefully, consider lifetime management, and write code that addresses these concerns correctly. In this column, I have set out to help developers who are consuming .NET or COM classes to better understand lifetime management, recognize situations where you can run into resource traps, and know how to solve these issues.
Note that, for clarity, the sample code shown in the column only works for single-threaded applications. Reusable thread-safe code for .NET resource management is available in the LifeTimeScope.net project on CodePlex (see codeplex.com/lifetimescope).
In .NET programming, an object is created with the new keyword and allocated on the managed heap. The object is alive until the garbage collector finds out that the object is no longer reachable from a strong root reference via a path of strong references. Each program has a main method and an associated class as well as static classes that all might contain local variables, static members, or even events. These static or local references are considered to be root references within your program (see Figure 1). Ordinary .NET Framework references are known to be strong references. Object lifetime is determined by the path of strong references that point from a root reference to an object.
Figure 1 Strong References to Objects on the Heap 
In some cases, such as when building a fast cache or a hash into an object graph, it might be interesting to have additional references to objects that do not change the lifetime of an object. For this purpose the .NET Framework offers an additional class called WeakReference that allows you to implement a weak reference between objects. This weak reference is ignored when determining the lifetime of an object.
Events can also be strong root references and as such can contribute to the strong reference path and thus affect the lifetime of an object. Ordinary events in the common language runtime (CLR) 2.0 are bidirectional strong references between the event source and the listener and as such can keep an object (either source or listener) alive that otherwise should be dead already. This is why a WeakEvent class was added in the .NET Framework 3.0. It is important that you become familiar with the WeakEvent pattern, which is not yet well known, but is required to implement the Observer pattern successfully. The WeakEvent pattern has been used in the Windows® Presentation Foundation (WPF) Data Binding implementation to prevent leakage due to data binding.

Garbage Collection and Finalization
Let's look at how the CLR determines whether an object is still alive and what happens when it isn't. In the November 2000 issue of MSDN® Magazine (msdn.microsoft.com/msdnmag/issues/1100/GCI), Jeffrey Richter describes the procedure. Each .NET process runs a separate thread that is used by the garbage collector. When the garbage collector runs, all other threads are paused. The garbage collector analyzes the memory structures and references to find out which objects are dead. These objects are then queued for a process called finalization. In a second phase, the finalization process is executed on the separate thread used by the garbage collector and the Finalizer method is called on each object.
There are two important points to note in this process. First, the Finalizer is called from a different thread than the thread that created the object. Second, the Finalizer is called at some point in time but not necessarily close to the time the object actually went dead (this can be noticed when the system is stressed, but memory is available).
The garbage collector is exposed in the static System.GC class. You can force garbage collection to run and let it identify the dead objects and queue them for finalization by calling GC.Collect. You can also force finalization to happen for all queued objects by calling GC.WaitForPendingFinalizers. However, there are two issues with calling WaitForPendingFinalizers: this is a time-consuming process and the Finalizers are called from another thread. This can lead to performance and threading issues if, for example, you need to release a reference to a system resource and plan to do this in your Finalizer—some unmanaged resources are thread-dependent. (In that case, please read on and learn about the Dispose pattern.)
As the .NET Framework team already identified the need for a timely destruction of objects and also the need for allowing the destruction code to be executed on a specific thread, they came up with a solution known as the Dispose pattern. For details, see the CLR Inside Out column in the July 2007 issue of MSDN Magazine at msdn.microsoft.com/msdnmag/issues/07/07/CLRInsideOut.
The Dispose pattern is a convention that should be implemented by every object that has resources and needs timely destruction. It is accomplished by implementing the IDisposable interface and releasing resources in the implementation of a method called Dispose exposed by the interface. However, just like in the unmanaged world, it is still the burden of the programmer to make sure the Dispose method is called at the right time in the client code. Brian Harry has a posting on his public forum that explains why the team came up with this solution and why other interesting solutions could not be applied successfully (see discuss.develop.com/archives/wa.exe?A2=ind0010A&L=DOTNET&P=R28572). The Dispose pattern must be correctly implemented for all objects that own resources.

Lifetime Management in COM
In the COM world, lifetime management works via reference counting. Each COM object has an internal count of client references that point to it. These counters are incremented and decremented by the client developer by calling IUnknown::AddRef and IUnknown::Release. Note that AddRef increases the counter and should be called when a reference to the component is set while Release decreases the counter and should be called when the reference has been destroyed. When the counter goes back to 0, the object can be destroyed.
The calls to AddRef and Release were eased by the use of SmartPointers in Active Template Library (ATL) or by generating the necessary code by the compiler/runtime such as in Visual Basic® 6.0. Events were only strong pointers in one direction and weak pointers in the other direction.
The two major issues with reference counting are performance loss and the potential to be unable to detect dead objects that are part of a cyclic-reference scenario. The performance loss is generally acceptable in COM because it's typically used as a technology to combine larger components. The .NET Framework, however, is used on the class level and thus the performance impact would be too great if reference counting were added to the CLR.
If you use a COM component from managed code, you use tlbimp.exe to generate a so-called runtime callable wrapper (RCW), which exposes the functionality of the COM component to the managed world. Note that tlbimp.exe is executed in the background when you reference a COM component in Visual Studio®. You can easily identify RCWs as they are displayed as System.__ComObject in the debugger. They are .NET types that hold one unmanaged pointer to the COM object and call AddRef and Release on the object. AddRef is called once the component is created and Release is called when the RCW is finalized.
But when is the RCW finalized? You do not know, so you need a method to call Dispose on the RCW. Unfortunately, the generated RCWs do not implement IDisposable. Currently, the equivalent to calling the missing Dispose method is to call:
System.Runtime.InteropServices.Marshal.ReleaseComObject(MyCOMObject)

.NET Deterministic Finalization
In many cases you need to make sure that the resources you use are released as soon as possible. The ideal way is through the using keyword in C# to ensure that the Dispose method is called on the object once program flow leaves the scope indicated by the curly brackets:
using (FileStream theFileStream = File.Create("C:\\hello.txt"))
{
    string s = theFileStream.Name; 
}
In addition, it's worth noting that C++/CLI automatically calls the destructor of local variables when exiting a method. In these scenarios, you can generally assume that the Dispose method is called automatically at the end of the block or method.
However, these approaches do not work when the usage scope of the resource is not local. Assume you call another method in the preceding code that uses the FileStream object as an input parameter. That method may not call Dispose or use the using keyword. In the context of a multithreaded server sharing resources between threads, this might become even more complex.
Unfortunately C# does not provide a simple construct equivalent to the using keyword that can be used across scopes or threads. This makes reusing code and routines difficult as the responsibility of calling Dispose must be negotiated between components to ensure it is done only once, and at the right time.
Beware: if you do not call Dispose explicitly, then the Finalizer will do it for sure if the object implements the Dispose pattern properly. However, you risk running out of resources under high loads because you do not know when the Finalizer will be called. You also risk having the Finalizer fail when it is called from another thread than the one that created the object. This can become an issue if you try to release unmanaged resources or COM resources in a Finalizer.
One possible solution is to build a generic wrapper class around any type implementing IDisposable. The wrapper class returns an IDisposable interface, but internally sets a reference counter before delegating the call to the component. The code shown in Figure 2 uses a new extension method, called AddRef, to get a corresponding wrapper object that contains an internal reference counter for a specific object.
When AddRef is called, the code looks into a hash table to see if the object already has a wrapper. If so, it returns the wrapper and increases the counter; otherwise it creates a new wrapper and adds it to the hash table. When the program reaches the end of the using block, Dispose is called automatically and it decrements the counter. In case the counter goes to zero, the Dispose call is propagated to the underlying object.
The implementation of the extension method and wrapper is shown in Figure 3. For clarity, this code is not designed to be thread safe.
Make sure that your Finalizers really run to the end. The .NET Framework runtime provides a concept called Constrained Execution Regions and the CriticalFinalizerObject that can help you achieve this.

Finalization in a COM Library
Let's look at a scenario where you use a COM object model from C#. You can use any COM component easily by creating a reference to its registered type library. Let's assume you have a COM component exposing a telephone API (TAPI) and use it in the following lines of code—see if you can find a bug related to lifetime management here:
void foo (CTAPIApplication TAPIApplication){
    string s = TAPIApplication.Ports[0].SpeechListener.GetName();
}
The bug is that a Ports collection was acquired from the object model, but its ReleaseComObject method was not called. The same is true for SpeechListener. You may argue that it is not safe to assume that foo should release the ComObject, and you are right; it is not clear from this code who should release the object and when. So what can you do?
The solution is again to use the AddRef Method, but you need to modify the RefCounted class to understand that it must call ReleaseComObject in case it is a ComObject. Figure 4 shows the enhanced FinalDispose method. In addition, where T : IDisposable was removed from the call to AddRef<T> because there is no common interface that IDisposable and COM Objects share:
public static RefCounted<T> AddRef<T>(this T resource)
Now you can rewrite the call into the telephone API as shown in Figure 5. While this code still is not very handy, it is very safe because the using statement ensures that ReleaseComObject really gets called even if an exception is thrown at some point. Adding another helper class called LifeTimeScope and changing the return type of AddRef makes the code even more readable:
void foo (CTAPIApplication TAPIApplication)
{
    using (new LifeTimeScope())
    {
        string s = 
            TAPIApplication.Ports.AddRef()[0].AddRef()
            .SpeechListener.AddRef().GetName();
    }
}
The LifeTimeScope class, shown in Figure 6, acts as a helper to call Dispose on all object wrappers that were touched by AddRef within a using block. AddRef got a few changes as well (see Figure 7). While these are all good changes, you still need to make the call to AddRef yourself.

Memory Leaks
The most common issue you will run into is that your application leaks memory due to event subscriptions. For example, you could write a Windows Forms user control that subscribes to the NetworkChange event in its constructor like this:
NetworkChange.NetworkAvailabilityChanged += new 
    NetworkAvailabilityChangedEventHandler(ctrl_NetAvailChangedHandler);
The user control and the NetworkAvailabilityChanged static class hold bidirectionally strong references to each other. Because NetworkAvailabilityChanged is a static root reference, the user control will not get released from memory until the event handler is removed.
If you don't unsubscribe an event from an object that exceeds the lifetime of its referenced object—in this case NetworkAvailabilityChanged and its referenced user control—you automatically create a memory leak. This problem is a common one and applies to all sorts of Observer pattern scenarios, including data binding.
The .NET Framework 2.0 documentation says you should unsubscribe the event in the Dispose method of the object. It's also a good idea to make sure Dispose is called. That's because in the .NET Framework 2.0 world events are resources that you need to care about. However, in the .NET Framework 3.0 you can employ a solution based on the WeakEvent pattern.
Finally, another way to assure destruction of unmanaged resources is by using the HandleCollector class, which helps you run GC.Collect occasionally. Figure 8 provides an example Create an instance of HandleCollector by providing three parameters: Handle Name (string), Initial Threshold (int), and Maximum Threshold (int). The initial threshold is the point at which the garbage collector can start performing garbage collection. The maximum threshold is the point at which the garbage collector must perform garbage collection.
This was a brief overview of lifetime management in .NET or COM classes. I hope you can now recognize and solve these issues. For more information, please visit the links in the "Lifetime Management Resources" sidebar.

Send your questions and comments to clrinout@microsoft.com.


Tim Fischer lives in Germany and is a Program Manager for Visual Studio and Expression products at Microsoft. He holds a degree in computer science from the University of Stuttgart and worked for 12 years as a consultant for model-driven development. He is the founder of tangible engineering, a company dedicated to building world-class .NET software factories.

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.
Page view tracker