HandleRef (Estructura)
TOC
Collapse the table of content
Expand the table of content

HandleRef (Estructura)

Actualización: noviembre 2007

Incluye un objeto administrado que contiene un identificador de un recurso que se pasa al código no administrado invocando a la plataforma.

Espacio de nombres:  System.Runtime.InteropServices
Ensamblado:  mscorlib (en mscorlib.dll)

[ComVisibleAttribute(true)]
public struct HandleRef
/** @attribute ComVisibleAttribute(true) */
public final class HandleRef extends ValueType
JScript admite el uso de estructuras, pero no admite la declaración de estructuras nuevas.

Si se utiliza la invocación de plataforma para llamar a un objeto administrado y no se hace referencia al objeto en ningún otro lugar después de la llamada de invocación de plataforma, es posible que el recolector de elementos no utilizados finalice el objeto administrado. Esta acción libera el recurso e invalida el identificador, lo que hace que se produzca un error en la llamada con invocación de plataforma. El hecho de incluir el identificador en un contenedor mediante HandleRef garantiza que el objeto administrado no se recoja cuando se realice la recolección de elementos no utilizados hasta que termine la llamada de invocación de plataforma. Para obtener una descripción de los servicios de invocación de plataforma, vea Consumir funciones DLL no administradas.

El tipo de valor HandleRef, al igual que GCHandle, es un tipo especial reconocido por el contador de referencias de interoperabilidad. Un GCHandle normal y no fijo impide también la recolección prematura de elementos no utilizados, pero HandleRef proporciona un mejor rendimiento. Aunque se prefiere el uso de HandleRef para mantener un objeto activo mientras dure una llamada de invocación de plataforma, se puede utilizar también el método GC.KeepAlive para el mismo fin.

El constructor HandleRef utiliza dos parámetros: un Object que representa el contenedor y un IntPtr que representa el identificador no administrado. El contador de referencias de interoperabilidad sólo pasa el identificador al código no administrado y garantiza que el contenedor (que se pasa como primer parámetro al constructor de HandleRef) continúe activo mientras dure la llamada.

En el siguiente ejemplo se muestra la forma de utilizar HandleRef para mantener activo un objeto que se pasa como primer parámetro. El contador de referencias de interoperabilidad sólo pasa el identificador al código no administrado.


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

    }
}


Todos los miembros static (Shared en Visual Basic) públicos de este tipo son seguros para la ejecución de subprocesos. No se garantiza que los miembros de instancias sean seguros para la ejecución de subprocesos.

Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98

.NET Framework y .NET Compact Framework no admiten todas las versiones de cada plataforma. Para obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

.NET Framework

Compatible con: 3.5, 3.0, 2.0, 1.1, 1.0

Adiciones de comunidad

AGREGAR
Mostrar:
© 2016 Microsoft