Questo articolo è stato tradotto automaticamente. Per visualizzare l'articolo in inglese, selezionare la casella di controllo Inglese. È possibile anche visualizzare il testo inglese in una finestra popup posizionando il puntatore del mouse sopra il testo.
Traduzione
Inglese

Esempio di HandleRef

In questo esempio viene dimostrato come evitare la procedura di Garbage Collection su un oggetto gestito prima del completamento della funzione non gestita. Viene inoltre illustrato come utilizzare l'overload di funzione per passare un riferimento null (Nothing in Visual Basic) anziché un riferimento a un tipo di valore.

Nell'esempio di HandleRef viene utilizzata la seguente funzione non gestita, illustrata con la dichiarazione di funzione originale:

  • ReadFile esportata da Kernel32.dll.

    BOOL ReadFile(
       HANDLE hFile, 
       LPVOID lpBuffer, 
       DWORD nNumberOfBytesToRead, 
       LPDWORD lpNumberOfBytesRead, 
       LPOVERLAPPED lpOverlapped);
    

La struttura originale passata alla funzione contiene i seguenti elementi:

typedef struct _OVERLAPPED { 
    ULONG_PTR  Internal; 
    ULONG_PTR  InternalHigh; 
    DWORD  Offset; 
    DWORD  OffsetHigh; 
    HANDLE hEvent; 
} OVERLAPPED; 

In questo esempio la struttura Overlapped e la classe Overlapped2 contengono i tipi IntPtr invece dei tipi di puntatore e del tipo HANDLE. L'attributo StructLayoutAttribute viene impostato in modo che i membri vengano disposti in sequenza nella memoria, nell'ordine in cui appaiono.

La classe LibWrap contiene i prototipi gestiti dei metodi ReadFile e ReadFile2. ReadFile passa la struttura Overlapped come uno dei parametri. Mediante l'overload del metodo ReadFile, se necessario è possibile passare nell'esempio un riferimento null (Nothing in Visual Basic) anziché un riferimento alla struttura. Né in C# né in Visual Basic 2005 è possibile passare direttamente un riferimento null (Nothing).

ReadFile2 passa la classe Overlapped2. Le classi, che sono tipi di riferimento, vengono passate come parametri in per impostazione predefinita. L'applicazione degli attributi InAttribute e OutAttribute alla dichiarazione provoca il marshalling di Overlapped2 come parametro in/out. L'esempio consente di passare direttamente un riferimento null (Nothing) anziché una classe, se necessario, poiché le classi costituiscono tipi di riferimento al posto dei quali è possibile passare un riferimento null (Nothing). Con la classe App viene creato un wrapper HandleRef per FileStream per evitare la procedura di Garbage Collection prima del completamento delle chiamate a ReadFile o ReadFile2.


// Declares a managed structure for the unmanaged structure.
[StructLayout(LayoutKind.Sequential)]
public struct Overlapped
{
    // ...
}

// Declares a managed class for the unmanaged structure.
[StructLayout(LayoutKind.Sequential)]
public class Overlapped2
{
    // ...
}

public class LibWrap
{
   // Declares managed prototypes for unmanaged functions.
   // Because Overlapped is a structure, you cannot pass null as a
   // parameter. Instead, declares an overloaded method.
    [DllImport("Kernel32.dll")]
    public static extern bool ReadFile(
        HandleRef hndRef,
        StringBuilder buffer,
        int numberOfBytesToRead,
        out int numberOfBytesRead,
        ref Overlapped flag );

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

    // Because Overlapped2 is a class, you can pass null as parameter.
    // No overloading is needed.
    [DllImport("Kernel32.dll", 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()
    {
        FileStream fs = new FileStream("HandleRef.txt", FileMode.Open);
        // Wraps the FileStream handle in HandleRef to prevent it
        // from being garbage collected before the call ends.
        HandleRef hr = new HandleRef(fs, fs.SafeFileHandle.DangerousGetHandle());
        StringBuilder buffer = new StringBuilder(5);
        int read = 0;
        // Platform invoke holds a reference to HandleRef until the call
        // ends.
        LibWrap.ReadFile(hr, buffer, 5, out read, IntPtr.Zero);
        Console.WriteLine("Read {0} bytes with struct parameter: {1}", read, buffer);
        LibWrap.ReadFile2(hr, buffer, 5, out read, null);
        Console.WriteLine("Read {0} bytes with class parameter: {1}", read, buffer);
    }
}


Mostra: