Condividi tramite


Sincronizzazione e output sovrapposti

È possibile eseguire operazioni di I/O sincrone o asincrone (dette anche sovrapposte) su file, named pipe e dispositivi di comunicazione seriale. Le WriteFile, ReadFile, DeviceIoControl, WaitCommEvent, ConnectNamedPipee Le funzioni TransactNamedPipe possono essere eseguite in modo sincrono o asincrono. Le funzioniReadFileEx e WriteFileExpossono essere eseguite solo in modo asincrono.

Quando una funzione viene eseguita in modo sincrono, non restituisce fino al completamento dell'operazione. Ciò significa che l'esecuzione del thread chiamante può essere bloccata per un periodo indefinito mentre attende il completamento di un'operazione dispendiosa in termini di tempo. Le funzioni chiamate per un'operazione sovrapposta possono restituire immediatamente, anche se l'operazione non è stata completata. Ciò consente l'esecuzione in background di un'operazione di I/O dispendiosa in termini di tempo, mentre il thread chiamante è libero di eseguire altre attività. Ad esempio, un singolo thread può eseguire operazioni di I/O simultanee su handle diversi o anche operazioni di lettura e scrittura simultanee sullo stesso handle.

Per sincronizzare l'esecuzione con il completamento dell'operazione sovrapposta, il thread chiamante usa la funzioneGetOverlappedResult, la funzione GetOverlappedResultEx o una delle funzioni di attesa per determinare quando l'operazione sovrapposta è stata completata. È anche possibile utilizzare la macroHasOverlappedIoCompletedper eseguire il polling per il completamento.

Per annullare tutte le operazioni di I/O asincrone in sospeso, usare la funzioneCancelIoExe fornire una struttura diOVERLAPPEDche specifica la richiesta di annullamento. Usare la funzione diCancelIoper annullare le operazioni di I/O asincrone in sospeso rilasciate dal thread chiamante per l'handle di file specificato.

Le operazioni sovrapposte richiedono un file, una named pipe o un dispositivo di comunicazione creato con il flag FILE_FLAG_OVERLAPPED. Quando un thread chiama una funzione (ad esempio la funzione ReadFile) per eseguire un'operazione sovrapposta, il thread chiamante deve specificare un puntatore a una strutturaOVERLAPPED. Se questo puntatore è NULL, il valore restituito dalla funzione potrebbe indicare erroneamente che l'operazione è stata completata. Tutti i membri della struttura OVERLAPPED devono essere inizializzati su zero, a meno che non venga usato un evento per segnalare il completamento di un'operazione di I/O. Se viene utilizzato un evento, il membro hEvent della struttura OVERLAPPED specifica un handle per l'oggetto evento allocato. Il sistema imposta lo stato dell'oggetto evento su non assegnato quando viene restituita una chiamata alla funzione di I/O prima del completamento dell'operazione. Il sistema imposta lo stato dell'oggetto evento su segnalato al termine dell'operazione. È necessario un evento solo se sono presenti più operazioni di I/O in sospeso contemporaneamente. Se non viene usato un evento, ogni operazione di I/O completata segnalerà il file, la named pipe o il dispositivo di comunicazione.

Quando viene chiamata una funzione per eseguire un'operazione sovrapposta, l'operazione potrebbe essere completata prima della restituzione della funzione. In questo caso, i risultati vengono gestiti come se l'operazione fosse stata eseguita in modo sincrono. Se l'operazione non è stata completata, tuttavia, il valore restituito della funzione è FALSEe la funzione GetLastError restituisce ERROR_IO_PENDING.

Un thread può gestire le operazioni sovrapposte tramite uno dei due metodi seguenti:

  • Usare ilGetOverlappedResulto funzione GetOverlappedResultEx per attendere il completamento dell'operazione sovrapposta. Se si usa GetOverlappedResultEx, il thread chiamante può specificare un timeout per l'operazione sovrapposta o eseguire un'attesa avvisabile.
  • Specificare un handle per l'oggetto evento di reimpostazione manuale della struttura OVERLAPPED in una delle funzioni di attesa e quindi, dopo la restituzione della funzione di attesa, chiamare GetOverlappedResult o GetOverlappedResultEx. La funzione restituisce i risultati dell'operazione sovrapposta completata e per le funzioni in cui tali informazioni sono appropriate, segnala il numero effettivo di byte trasferiti.

Quando si eseguono più operazioni sovrapposte simultanee su un singolo thread, il thread chiamante deve specificare una strutturaOVERLAPPEDper ogni operazione. Ogni struttura di OVERLAPPED deve specificare un handle per un oggetto evento di reimpostazione manuale diverso. Per attendere il completamento di una delle operazioni sovrapposte, il thread specifica tutti gli handle di eventi di reimpostazione manuale come criteri di attesa in una delle funzioni di attesa oggetti multipli. Il valore restituito della funzione di attesa a più oggetti indica quale oggetto evento di reimpostazione manuale è stato segnalato, in modo che il thread possa determinare quale operazione sovrapposta ha causato il completamento dell'operazione di attesa.

È più sicuro usare un oggetto evento separato per ogni operazione sovrapposta, anziché specificare alcun oggetto evento o riutilizzare lo stesso oggetto evento per più operazioni. Se non viene specificato alcun oggetto evento nella strutturaOVERLAPPED, il sistema segnala lo stato del file, della named pipe o del dispositivo di comunicazione al termine dell'operazione sovrapposta. Pertanto, è possibile specificare questi handle come oggetti di sincronizzazione in una funzione di attesa, anche se il loro uso a questo scopo può essere difficile da gestire perché, quando si eseguono operazioni sovrapposte simultanee sullo stesso file, named pipe o dispositivo di comunicazione, non è possibile sapere quale operazione ha causato la segnalazione dello stato dell'oggetto.

Un thread non deve riutilizzare un evento presupponendo che l'evento venga segnalato solo dall'operazione sovrapposta del thread. Viene segnalato un evento sullo stesso thread dell'operazione sovrapposta che viene completata. L'uso dello stesso evento su più thread può causare una race condition in cui l'evento viene segnalato correttamente per il thread la cui operazione viene completata per prima e prematuramente per altri thread che usano tale evento. Al termine dell'operazione sovrapposta successiva, l'evento viene segnalato nuovamente per tutti i thread che usano tale evento e così via fino al completamento di tutte le operazioni sovrapposte.

Per esempi che illustrano l'uso di operazioni sovrapposte, routine di completamento e funzione di GetOverlappedResult, vedere Using Pipes.

Windows Vista, Windows Server 2003 e Windows XP:

Prestare attenzione quando si riutilizzano strutture di OVERLAPPED. Se strutture di OVERLAPPED vengono riutilizzate in più thread e viene chiamato GetOverlappedResult con il parametro bWait impostato su TRUE, il thread chiamante deve assicurarsi che l'evento associato venga segnalato prima di riutilizzare la struttura. Questa operazione può essere eseguita usando la funzione WaitForSingleObject dopo aver chiamato GetOverlappedResult per forzare il thread a attendere il completamento dell'operazione. Si noti che l'oggetto evento deve essere un oggetto evento di reimpostazione manuale. Se viene utilizzato un oggetto evento autoreset, la chiamata di GetOverlappedResult con il parametro bWait impostato su TRUE fa sì che la funzione venga bloccata a tempo indeterminato. Questo comportamento è cambiato a partire da Windows 7 e Windows Server 2008 R2 per le applicazioni che specificano Windows 7 come sistema operativo supportato nel manifesto dell'applicazione. Per altre informazioni, vedere manifesti dell'applicazione .

concetti di I/O