RESOLUTION
The resolution to this problem depends on the nature of the unmanaged resource. For the purpose of this article, unmanaged resources fall into two catagories:
- Resources that are handles to operating system objects.
- Resources that are not handles to operating system objects.
When you use Interop Services, there are two mechanisms for interoperating with unmanaged code. One is the Platform Invoke Service, which allows managed code to call unmanaged functions that are implemented in dynamic-link libraries (DLLs). The other mechanism is COM Interop, which is a bi-directional service that bridges between the .NET Framework and COM components.
PInvoke and Handles to Operating System Objects
When you work with handles to operating system objects, such as window handles and device contexts, use the
HandleRef structure to wrap the resources. Platform Interop Services works with the
HandleRef structure.
Note In the following COM Interop example, this problem is resolved by making calls to the
KeepAlive method of the Garbage Collector. Although this will work with Platform Invoke calls,
HandleRef is the recommended approach.
Option Strict On
Option Explicit On
Imports System.Runtime.InteropServices
Module Module1
Private Declare Function GetGraphicsMode Lib "gdi32" Alias "GetGraphicsMode" _
(ByVal hdc As HandleRef) As Integer
Private Declare Function GetDC Lib "user32" _
(ByVal hwnd As IntPtr) As IntPtr
Private Declare Function ReleaseDC Lib "user32" _
(ByVal hwnd As IntPtr, ByVal hdc As HandleRef) As Integer
Class Test
Public hdcscreen As HandleRef
Public Sub New()
hdcscreen = New HandleRef(Me, GetDC(IntPtr.Zero))
End Sub
Protected Overrides Sub Finalize()
Dim ret As Integer
ret = ReleaseDC(IntPtr.Zero, hdcscreen)
MyBase.Finalize()
End Sub
End Class
Sub Main()
Dim mvb As New Test()
Dim GrMode As Integer
GrMode = GetGraphicsMode(mvb.hdcscreen)
Console.Write(GrMode.ToString)
End Sub
End Module
COM Interop and Other Types of Resources
For resources where
HandleRef is not applicable, such as a database connection, use
GC.KeepAlive to maintain an object's existence, as in the following sample code:
Imports System
Imports System.Reflection
Module MyModule
Sub Main()
Dim conn = Activator.CreateInstance(Type.GetTypeFromProgId("ADODB.Connection"))
conn.Open _
("Provider=SQLOLEDB.1;Data Source=(local);Integrated Security=SSPI;Initial Catalog=pubs")
Dim rs = conn.Execute("SELECT * FROM employee")
Dim id
If Not rs.EOF Then
id = rs("emp_id").Value
Console.WriteLine(id)
Else
Console.WriteLine("Empty Recordset")
End If
GC.KeepAlive(conn)
GC.KeepAlive(rs)
GC.KeepAlive(id)
End Sub
End Module
For more about automatic memory management, visit the following Microsoft Developer Network Web site: