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)
The HandleRef type exposes the following members.
| Name | Description | |
|---|---|---|
![]() | Equals | Indicates whether this instance and a specified object are equal. (Inherited from ValueType.) |
![]() | Finalize | Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection. (Inherited from Object.) |
![]() | GetHashCode | Returns the hash code for this instance. (Inherited from ValueType.) |
![]() | GetType | Gets the Type of the current instance. (Inherited from Object.) |
![]() | MemberwiseClone | Creates a shallow copy of the current Object. (Inherited from Object.) |
![]() ![]() | ToIntPtr | Returns the internal integer representation of a HandleRef object. |
![]() | ToString | Returns the fully qualified type name of this instance. (Inherited from ValueType.) |
| Name | Description | |
|---|---|---|
![]() ![]() | Explicit(HandleRef to IntPtr) | Returns the handle to a resource of the specified HandleRef object. |
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 namespace System::Runtime::InteropServices; using namespace System; using namespace System::IO; using namespace System::Text; using namespace System::Runtime::InteropServices; /* typedef struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; DWORD Offset; DWORD OffsetHigh; HANDLE hEvent; } OVERLAPPED; */ // declared as structure [StructLayout(LayoutKind::Sequential)] public value struct Overlapped { private: IntPtr intrnal; IntPtr internalHigh; int offset; int offsetHigh; IntPtr hEvent; }; // declared as class [StructLayout(LayoutKind::Sequential)] public ref class Overlapped2 { private: IntPtr intrnal; IntPtr internalHigh; int offset; int offsetHigh; IntPtr hEvent; }; public ref class LibWrap { public: // 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)] static bool ReadFile( HandleRef hndRef, StringBuilder^ buffer, int numberOfBytesToRead, [Out]int * numberOfBytesRead, 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)] static 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")] static bool ReadFile2( HandleRef hndRef, StringBuilder^ buffer, int numberOfBytesToRead, [Out]int * numberOfBytesRead, Overlapped2^ flag ); }; int main() { FileStream^ fs = gcnew FileStream( "HandleRef.txt", FileMode::Open ); HandleRef hr = HandleRef(fs,fs->Handle); StringBuilder^ buffer = gcnew StringBuilder( 5 ); int read = 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, nullptr ); Console::WriteLine( "Read with class parameter: {0}", buffer ); }
Windows 7, Windows Vista SP1 or later, Windows XP SP3, Windows XP SP2 x64 Edition, Windows Server 2008 (Server Core not supported), Windows Server 2008 R2 (Server Core supported with SP1 or later), Windows Server 2003 SP2
The .NET Framework does not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.
