HandleRef Structure
Wraps a managed object holding a handle to a resource that is passed to unmanaged code using platform invoke.
Assembly: mscorlib (in mscorlib.dll)
If you use platform invoke to call a managed object, and the object is not referenced elsewhere after the platform invoke call, it is possible for the garbage collector to finalize the managed object. This action releases the resource and invalidates the handle, causing the platform invoke call to fail. Wrapping a handle with HandleRef guarantees that the managed object is not garbage collected until the platform invoke call completes. For a description of platform invoke services, see Consuming Unmanaged DLL Functions.
The HandleRef value type, like GCHandle, is a special type recognized by the interop marshaler. A normal, nonpinned GCHandle also prevents untimely garbage collection, yet HandleRef provides better performance. Although using HandleRef to keep an object alive for the duration of a platform invoke call is preferred, you can also use the GC.KeepAlive method for the same purpose.
The HandleRef constructor takes two parameters: an Object representing the wrapper, and an IntPtr representing the unmanaged handle. The interop marshaler passes only the handle to unmanaged code, and guarantees that the wrapper (passed as the first parameter to the constructor of the HandleRef) remains alive for the duration of the call.
The following example shows how to use HandleRef to keep alive an object passed as the first parameter. The interop marshaler passes only the handle to unmanaged code.
' HandleRef.vb Imports System Imports System.IO Imports System.Text Imports System.Runtime.InteropServices Imports System.Security.Permissions 'typedef struct _OVERLAPPED { ' ULONG_PTR Internal; ' ULONG_PTR InternalHigh; ' DWORD Offset; ' DWORD OffsetHigh; ' HANDLE hEvent; '} OVERLAPPED; ' declared as structure <StructLayout(LayoutKind.Sequential)> _ Public Structure Overlapped Private intrnal As IntPtr Private internalHigh As IntPtr Private offset As Integer Private offsetHigh As Integer Private hEvent As IntPtr End Structure 'Overlapped ' declared as class <StructLayout(LayoutKind.Sequential)> _ Public Class Overlapped2 Private intrnal As IntPtr Private internalHigh As IntPtr Private offset As Integer Private offsetHigh As Integer Private hEvent As IntPtr End Class 'Overlapped2 Public Class LibWrap ' to prevent FileStream to be GC-ed before call ends, ' its handle should be wrapped in HandleRef ' BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, ' LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); Overloads Declare Unicode Function ReadFile Lib "Kernel32.dll" ( _ ByVal hndRef As HandleRef, _ ByVal buffer As StringBuilder, _ ByVal numberOfBytesToRead As Integer, _ ByRef numberOfBytesRead As Integer, _ ByRef flag As Overlapped) _ As Boolean ' since Overlapped is struct, Nothing can't be passed instead, ' we must declare overload method if we will use this Overloads Declare Unicode Function ReadFile Lib "Kernel32.dll" ( _ ByVal hndRef As HandleRef, _ ByVal buffer As StringBuilder, _ ByVal numberOfBytesToRead As Integer, _ ByRef numberOfBytesRead As Integer, _ ByVal flag As Integer) _ As Boolean ' int instead of structure reference ' since Overlapped2 is class, we can pass Nothing as parameter ' no overload is needed Declare Unicode Function ReadFile2 Lib "Kernel32.dll" Alias "ReadFile" ( _ ByVal hndRef As HandleRef, _ ByVal buffer As StringBuilder, _ ByVal numberOfBytesToRead As Integer, _ ByRef numberOfBytesRead As Integer, _ <[In](), Out()> ByVal flag As Overlapped2) _ As Boolean End Class 'LibWrap Public Class App Public Shared Sub Main() Run() End Sub 'Main <SecurityPermissionAttribute(SecurityAction.Demand, Flags:=SecurityPermissionFlag.UnmanagedCode)> _ Public Shared Sub Run() Dim fs As New FileStream("HandleRef.txt", FileMode.Open) Dim hr As New HandleRef(fs, fs.SafeFileHandle.DangerousGetHandle()) Dim buffer As New StringBuilder(5) Dim read As Integer = 0 ' platform invoke will hold reference to HandleRef until call ends LibWrap.ReadFile(hr, buffer, 5, read, 0) Console.WriteLine("Read with struct parameter: {0}", buffer) LibWrap.ReadFile2(hr, buffer, 5, read, Nothing) Console.WriteLine("Read with class parameter: {0}", buffer) End Sub 'Run End Class 'App
Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98
The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.