H o m e

 

R e l e a s i n g    C O M    O b j e c t s    W i t h    V B . N E T    

By Michael McIntyre

mikemc@getdotnetcode.com

 

This article discusses the special handling required to release COM objects used by VB.NET programs.

 

COM objects are designed to be destroyed the instant a hosting application finishes using them.

 

COM and the CLR manage the lifetime of objects differently. In Visual Basic 6 code, setting the last reference to a COM object to Nothing triggers destruction of the COM object.  In Visual Basic.NET, setting the last reference of a COM object to Nothing does not immediately trigger the destruction of a COM object.

 

Let’s first examine how Visual Basic 6 manages COM object lifetimes, next examine how .NET handles COM object lifetimes, and finally examine what Visual Basic.NET code must include to destroy COM objects the instant an application finishes using them.

 

 

Visual Basic 6

 

COM uses reference counting to control object lifetime. Visual Basic 6 programmers are in the habit of assigning a value of Nothing to a COM reference variable to release a COM object.  This action causes the Visual Basic 6 runtime to issue a Release call to the COM object. Once there are zero references remaining to the COM object, the COM object’s Class_Terminate method will be executed and the COM object will remove itself from memory.

 

Code Example – VB6

 

' Instantiate a Person COM object.

Dim person1 As Person

Set person1 = New Person

 

' Call the SayName method of Person COM object.

person1.SayName

 

' Release the Person COM object.

Set person1 = Nothing  ' Class_Terminate fires here.

 

Visual Basic.NET

 

A reference type variable in your VB.NET code holds a reference to a COM object through a runtime callable wrapper (RCW) object.  .NET code can not directly reference a COM object.  Instead, the .NET COM interoperability layer creates a special proxy – the RCW – which is inserted between the managed reference in your code and the COM object. You can think of the RCW as a sort of middle-man that manages the flow of execution between .NET managed code and a COM object’s unmanaged code.

 

The lifetime of the RCW object and the COM object it manages is controlled by the .NET garbage collector. Because of this, special handling is required when COM objects are used in .NET managed code. Assigning a value of Nothing to a reference variable that accesses a COM object through a RCW object does not automatically cause the CLR to issue a Release call to the COM object.

 

Code Example – Visual Basic.NET release COM object (incorrect)

 

' Instantiate a Person COM object.

Dim person1 As Person

person1 = New Person

 

' Call the SayName method of Person COM object.

person1.SayName

 

' Try to release the Person COM object the VB6 way.

person1 = Nothing  ' Class_Terminate DOES NOT fire here.

 

Here’s what actually happens when the last line above executes.  Setting the person1 variable to nothing create an unreachable managed object – the RCW object that references the person1 COM object.  Both the RCW object and the person1 COM object remain alive in memory. 

 

Eventually, the garbage collector (GC) will determine the RCW object is unreachable and it will start the process to remove the RCW object and its associated COM object from memory.  At some unpredictable time in the future, when the GC finally gets around to releasing the two objects it will call Release on the COM object.  The COM object’s Class_Terminate method will finally be executed.

 

Because COM objects are designed to be destroyed the instant a hosting application finishes using them, letting the GC eventually get around to releasing COM objects is not generally recommended.

 

Instead of waiting for the GC to destroy a COM object, your code can explicitly call the System.Runtime.InteropServices.Marshal class’ shared ReleaseComObject method.  To use the ReleaseComObject method first import the namespace:

 

Imports System.Runtime.InteropServices

 

Example Code – Visual Basic.Net release COM object (correct)

 

' Instantiate a Person COM object.

Dim person1 As Person

person1 = New Person

 

' Call the SayName method of Person COM object.

person1.SayName

 

' Try to release the Person COM object the Visual Basic.NET way.

Marshal.ReleaseComObject(person1) ' Will cause Class_Terminate to fire.

 

The code above shows the proper technique for explicitly releasing a COM object using the ReleaseComObject method. The call to ReleaseComObject blocks the flow of execution while the RCW calls Release. The call will not return until the COM object has executed its destructor and removed itself from memory.

 

That’s NOT all, folks.

Using and destroying COM objects can be a simple as explained above, but not always. The more intensive your use of COM objects in your VB.NET programs the more likely you will need to consider other factors and scenarios.

 

Sam Gentile, MVP, is a person who has spent a lot of time exploring and troubleshooting COM.  Read his COM ‘tell all’ MSDN article at: Beyond (COM) Add Reference: Has Anyone Seen the Bridge? and read his COM blogs at: Sam Gentile.

 

 

 

Copyright © 2001-2004 aZ Software Developers. All rights reserved.