Export (0) Print
Expand All

HandleRef Structure

Wraps a managed object holding a handle to a resource that is passed to unmanaged code using platform invoke.

Namespace:  System.Runtime.InteropServices
Assembly:  mscorlib (in mscorlib.dll)

[ComVisibleAttribute(true)]
public struct HandleRef

The HandleRef type exposes the following members.

  NameDescription
Public methodHandleRefInitializes a new instance of the HandleRef class with the object to wrap and a handle to the resource used by unmanaged code.
Top

  NameDescription
Public propertyHandleGets the handle to a resource.
Public propertyWrapperGets the object holding the handle to a resource.
Top

  NameDescription
Public methodEqualsIndicates whether this instance and a specified object are equal. (Inherited from ValueType.)
Public methodGetHashCodeReturns the hash code for this instance. (Inherited from ValueType.)
Public methodGetTypeGets the Type of the current instance. (Inherited from Object.)
Public methodStatic memberToIntPtrReturns the internal integer representation of a HandleRef object.
Public methodToStringReturns the fully qualified type name of this instance. (Inherited from ValueType.)
Top

  NameDescription
Public operatorStatic memberExplicit(HandleRef to IntPtr)Returns the handle to a resource of the specified HandleRef object.
Top

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.cs 

using System;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
using 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 struct Overlapped
{
    IntPtr intrnal;
    IntPtr internalHigh;
    int offset;
    int offsetHigh;
    IntPtr hEvent;
}

// declared as class
[StructLayout(LayoutKind.Sequential)]
public class Overlapped2
{
    IntPtr intrnal;
    IntPtr internalHigh;
    int offset;
    int offsetHigh;
    IntPtr hEvent;
}

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);    

    [DllImport("Kernel32.dll", CharSet=CharSet.Unicode)]
    public static extern bool ReadFile(
        HandleRef hndRef,
        StringBuilder buffer,
        int numberOfBytesToRead,
        out int numberOfBytesRead,
        ref Overlapped flag);

    // since Overlapped is struct, null can't be passed instead,  
    // we must declare overload method if we will use this 

    [DllImport("Kernel32.dll", CharSet=CharSet.Unicode)]
    public static extern bool ReadFile(
        HandleRef hndRef,
        StringBuilder buffer,
        int numberOfBytesToRead,
        out int numberOfBytesRead,
        int flag);	// int instead of structure reference 

    // since Overlapped2 is class, we can pass null as parameter, 
    // no overload is needed	

    [DllImport("Kernel32.dll", CharSet=CharSet.Unicode, EntryPoint = "ReadFile")]
    public static extern bool ReadFile2(
        HandleRef hndRef,
        StringBuilder buffer,
        int numberOfBytesToRead,
        out int numberOfBytesRead,
        Overlapped2 flag);
}

public class App
{
    public static void Main()
    {
	Run();
    }

    [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
    public static void Run()
    {
        FileStream fs = new FileStream("HandleRef.txt", FileMode.Open);
        HandleRef hr = new HandleRef(fs, fs.SafeFileHandle.DangerousGetHandle());
        StringBuilder buffer = new StringBuilder(5);
        int read = 0;

        // platform invoke will hold reference to HandleRef until call ends

        LibWrap.ReadFile(hr, buffer, 5, out read, 0);
        Console.WriteLine("Read with struct parameter: {0}", buffer);
        LibWrap.ReadFile2(hr, buffer, 5, out read, null);
        Console.WriteLine("Read with class parameter: {0}", buffer);

    }
}

.NET Framework

Supported in: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Supported in: 4, 3.5 SP1

Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Server Core Role not supported), Windows Server 2008 R2 (Server Core Role supported with SP1 or later; Itanium not supported)

The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
Show:
© 2014 Microsoft