Delen via


Synchronisatie en overlappende invoer en uitvoer

U kunt synchrone of asynchrone I/O-bewerkingen uitvoeren op bestanden, named pipes en seriële communicatieapparaten. De WriteFile, ReadFile, DeviceIoControl, WaitCommEvent, ConnectNamedPipe-en TransactNamedPipe--functies kunnen synchroon of asynchroon worden uitgevoerd. De functies ReadFileEx en WriteFileEx kunnen alleen asynchroon worden uitgevoerd.

Wanneer een functie synchroon wordt uitgevoerd, wordt deze pas geretourneerd als de bewerking is voltooid. Dit betekent dat de uitvoering van de aanroepende thread voor onbepaalde tijd kan worden geblokkeerd terwijl wordt gewacht tot een tijdrovende bewerking is voltooid. Functies die worden aangeroepen voor overlappende bewerking, kunnen onmiddellijk worden geretourneerd, ook al is de bewerking niet voltooid. Hierdoor kan een tijdrovende I/O-bewerking op de achtergrond worden uitgevoerd terwijl de aanroepende thread vrij is om andere taken uit te voeren. Een enkele thread kan bijvoorbeeld gelijktijdige I/O-bewerkingen uitvoeren op verschillende ingangen, of zelfs gelijktijdige lees- en schrijfbewerkingen op dezelfde ingang.

Als u de uitvoering wilt synchroniseren met de voltooiing van de overlappende bewerking, gebruikt de aanroepende thread de GetOverlappedResult functie, de functie GetOverlappedResultEx of een van de wachtfuncties om te bepalen wanneer de overlappende bewerking is voltooid. U kunt ook de HasOverlappedIoCompleted macro gebruiken om te peilen naar voltooiing.

Als u alle in behandeling zijnde asynchrone I/O-bewerkingen wilt annuleren, gebruikt u de functie CancelIoEx en geeft u een OVERLAPPENDE structuur op waarmee de aanvraag wordt opgegeven die moet worden geannuleerd. Gebruik de functie CancelIo om in behandeling zijnde asynchrone I/O-bewerkingen te annuleren die zijn uitgegeven door de aanroepende thread voor de opgegeven bestandsingang.

Overlappende bewerkingen vereisen een bestand, benoemde pijp of communicatieapparaat dat is gemaakt met de vlag FILE_FLAG_OVERLAPPED. Wanneer een thread een functie aanroept (zoals de ReadFile functie) om een overlappende bewerking uit te voeren, moet de aanroepende thread een aanwijzer opgeven naar een OVERLAPPENDE structuur. (Als deze aanwijzer is NULL-, kan de retourwaarde van de functie onjuist aangeven dat de bewerking is voltooid.) Alle leden van de OVERLAPPENDE structuur moeten worden geïnitialiseerd tot nul, tenzij een gebeurtenis wordt gebruikt om de voltooiing van een I/O-bewerking te signaleren. Als een gebeurtenis wordt gebruikt, geeft de hEvent lid van de OVERLAPPED- structuur een ingang op voor het toegewezen gebeurtenisobject. Het systeem stelt de status van het gebeurtenisobject in op niet-ondertekend wanneer een aanroep naar de I/O-functie wordt geretourneerd voordat de bewerking is voltooid. Het systeem stelt de status van het gebeurtenisobject in op signalering wanneer de bewerking is voltooid. Een gebeurtenis is alleen nodig als er meerdere openstaande I/O-bewerkingen tegelijk zijn. Als een gebeurtenis niet wordt gebruikt, geeft elke voltooide I/O-bewerking het bestand, de benoemde pipe of het communicatieapparaat aan.

Wanneer een functie wordt aangeroepen om een overlappende bewerking uit te voeren, kan de bewerking worden voltooid voordat de functie wordt geretourneerd. Wanneer dit gebeurt, worden de resultaten verwerkt alsof de bewerking synchroon is uitgevoerd. Als de bewerking echter niet is voltooid, wordt de retourwaarde van de functie FALSEen retourneert de GetLastError-functie ERROR_IO_PENDING.

Een thread kan overlappende bewerkingen beheren met een van de volgende twee methoden:

  • Gebruik de functie GetOverlappedResult of functie GetOverlappedResultEx om te wachten totdat de overlappende bewerking is voltooid. Als GetOverlappedResultEx wordt gebruikt, kan de aanroepende thread een time-out opgeven voor de overlappende bewerking of een waarschuwingswachttijd uitvoeren.
  • Geef een ingang op voor het OVERLAPPENDE structuurgebeurtenisobject handmatig opnieuw instellen in een van de wachtfuncties en roep GetOverlappedResult of GetOverlappedResultExaan. De functie retourneert de resultaten van de voltooide overlappende bewerking en voor functies waarin dergelijke informatie van toepassing is, wordt het werkelijke aantal bytes gerapporteerd dat is overgedragen.

Wanneer u meerdere gelijktijdige overlappende bewerkingen uitvoert op één thread, moet de aanroepende thread een OVERLAPPENDE structuur voor elke bewerking opgeven. Elke OVERLAPPENDE structuur moet een ingang opgeven voor een ander gebeurtenisobject voor handmatig opnieuw instellen. Als u wilt wachten tot een van de overlappende bewerkingen is voltooid, geeft de thread alle gebeurtenis voor handmatig opnieuw instellen op als wachtcriteria in een van de wachtfuncties wachtfuncties. De retourwaarde van de wachtfunctie voor meerdere objecten geeft aan welk gebeurtenisobject handmatig opnieuw instellen is gesignaleerd, zodat de thread kan bepalen welke overlappende bewerking de wachtbewerking heeft veroorzaakt.

Het is veiliger om een afzonderlijk gebeurtenisobject te gebruiken voor elke overlappende bewerking, in plaats van geen gebeurtenisobject op te geven of hetzelfde gebeurtenisobject opnieuw te gebruiken voor meerdere bewerkingen. Als er geen gebeurtenisobject is opgegeven in de OVERLAPPENDE structuur, geeft het systeem de status van het bestand, de benoemde pijp of het communicatieapparaat aan wanneer de overlappende bewerking is voltooid. U kunt deze ingangen dus opgeven als synchronisatieobjecten in een wachtfunctie, hoewel het gebruik voor dit doel moeilijk te beheren is, omdat wanneer gelijktijdig overlappende bewerkingen op hetzelfde bestand, benoemde pijp of communicatieapparaat worden uitgevoerd, er geen manier is om te weten welke bewerking ervoor zorgde dat de status van het object werd gesignaleerd.

Een thread mag een gebeurtenis niet opnieuw gebruiken met de veronderstelling dat de gebeurtenis alleen wordt gesignaleerd door de overlappende bewerking van die thread. Een gebeurtenis wordt gesignaleerd op dezelfde thread als de overlappende bewerking die wordt voltooid. Het gebruik van dezelfde gebeurtenis op meerdere threads kan leiden tot een racevoorwaarde waarin de gebeurtenis correct wordt gesignaleerd voor de thread waarvan de bewerking eerst en voortijdig wordt voltooid voor andere threads die die gebeurtenis gebruiken. Wanneer de volgende overlappende bewerking is voltooid, wordt de gebeurtenis opnieuw gesignaleerd voor alle threads die deze gebeurtenis gebruiken, enzovoort totdat alle overlappende bewerkingen zijn voltooid.

Zie Pipes-gebruiken voor voorbeelden die het gebruik van overlappende bewerkingen, voltooiingsroutines en de functie GetOverlappedResult illustreren.

Windows Vista, Windows Server 2003 en Windows XP:

Wees voorzichtig bij het hergebruik van OVERLAPPENDE structuren. Als OVERLAPPENDE structuren opnieuw worden gebruikt op meerdere threads en GetOverlappedResult- wordt aangeroepen met de parameter bWait ingesteld op TRUE, moet de aanroepende thread ervoor zorgen dat de bijbehorende gebeurtenis wordt gesignaleerd voordat de structuur opnieuw wordt gebruikt. Dit kan worden bereikt met behulp van de functie WaitForSingleObject na het aanroepen van GetOverlappedResult- om af te dwingen dat de thread wacht totdat de bewerking is voltooid. Houd er rekening mee dat het gebeurtenisobject een gebeurtenisobject handmatig opnieuw moet instellen. Als een gebeurtenisobject voor automatisch opnieuw instellen wordt gebruikt, wordt GetOverlappedResult- aangeroepen met de parameter bWait ingesteld op TRUE ervoor zorgt dat de functie voor onbepaalde tijd wordt geblokkeerd. Dit gedrag is gewijzigd vanaf Windows 7 en Windows Server 2008 R2 voor toepassingen die Windows 7 opgeven als het ondersteunde besturingssysteem in het toepassingsmanifest. Zie toepassingsmanifestenvoor meer informatie.

I/O-concepten