Szinkronizálás és átfedésben lévő bemenet és kimenet
Szinkronizált vagy aszinkron (más néven átfedésben lévő) I/O-műveleteket végezhet fájlokon, nevesített csöveken és soros kommunikációs eszközökön. A WriteFile, ReadFile, DeviceIoControl, WaitCommEvent, ConnectNamedPipeés TransactNamedPipe függvények szinkron vagy aszinkron módon is végrehajthatók. A ReadFileEx és WriteFileEx függvények csak aszinkron módon hajthatók végre.
Ha egy függvényt szinkron módon hajt végre, a művelet befejezéséig nem tér vissza. Ez azt jelenti, hogy a hívószál végrehajtása határozatlan ideig blokkolható, amíg egy időigényes művelet befejeződik. Az átfedésben lévő művelethez hívott függvények azonnal visszatérhetnek, még akkor is, ha a művelet még nem fejeződött be. Ez lehetővé teszi egy időigényes I/O-művelet végrehajtását a háttérben, miközben a hívó szál szabadon végrehajthat más feladatokat. Egy szál például képes egyidejű I/O-műveleteket végrehajtani különböző leírókon, vagy akár egyidejű olvasási és írási műveleteket is ugyanazon a leírón.
Ha szinkronizálni szeretné a végrehajtást az átfedésben lévő művelettel, a hívószál a GetOverlappedResult függvényt, a GetOverlappedResultEx függvényt vagy a várakozási függvények egyikét használja, annak meghatározásához, hogy az átfedésben lévő művelet mikor fejeződött be. A HasOverlappedIoCompleted makróval is lekérdezheti a befejezést.
Az összes függőben lévő aszinkron I/O-művelet megszakításához használja a CancelIoEx függvényt, és adjon meg egy ÁTFEDÉSBEN lévő struktúrát, amely meghatározza a lemondási kérelmet. A CancelIo függvénnyel megszakíthatja a hívó szál által a megadott fájlleíróhoz kiadott aszinkron I/O-műveleteket.
Az átfedésben lévő műveletekhez olyan fájlra, elnevezett csőre vagy kommunikációs eszközre van szükség, amelyet a FILE_FLAG_OVERLAPPED jelzővel hoztak létre. Ha egy szál meghív egy függvényt (például a ReadFile függvényt) egy átfedésben lévő művelet végrehajtásához, a hívószálnak meg kell adnia egy mutatót egy ÁTFEDÉSBEN lévő struktúrára. (Ha ez a mutató NULL, a függvény visszatérési értéke helytelenül jelezheti a művelet befejezését.) Az ÁTFEDÉSBEN lévő szerkezet minden tagját nullára kell inicializálni, kivéve, ha egy esemény egy I/O-művelet befejezésének jelzésére szolgál. Ha eseményt használ, a hEvent tagja az ÁTFEDÉSBEN struktúra egy leírót határoz meg a lefoglalt eseményobjektumhoz. A rendszer az eseményobjektum állapotát aláíratlanra állítja, amikor az I/O függvény hívása a művelet befejezése előtt visszatér. A rendszer úgy állítja be az eseményobjektum állapotát, hogy jelezve legyen a művelet befejezésekor. Eseményre csak akkor van szükség, ha egyszerre több kiugró I/O-művelet is lesz. Ha nem használ eseményt, minden befejezett I/O-művelet jelzi a fájlt, az elnevezett csövet vagy a kommunikációs eszközt.
Ha egy függvényt egy átfedésben lévő művelet végrehajtására hív meg, a művelet még a függvény visszatérése előtt befejeződhet. Ha ez történik, a rendszer úgy kezeli az eredményeket, mintha a műveletet szinkron módon hajtották volna végre. Ha azonban a művelet nem fejeződött be, a függvény visszatérési értéke HAMIS, a GetLastError függvény pedig ERROR_IO_PENDING.
A szálak két módszerrel kezelhetik az átfedésben lévő műveleteket:
- Az GetOverlappedResult vagy GetOverlappedResultEx függvénnyel várja meg az átfedésben lévő művelet befejezését. Ha GetOverlappedResultEx van használatban, a hívószál megadhat egy időtúllépést az átfedésben lévő művelethez, vagy riasztási várakozást hajthat végre.
- Adjon meg egy fogópontot a ÁTFEDÉSBEN struktúra manuális alaphelyzetbe állítási eseményobjektumához az egyik várakozási függvényben, majd a várakozási függvény visszatérése után hívja meg GetOverlappedResult vagy GetOverlappedResultEx. A függvény visszaadja a befejezett átfedésben lévő művelet eredményeit, és azon függvények esetében, amelyekben az ilyen információk megfelelőek, az átvitt bájtok tényleges számát jelenti.
Ha több egyidejű átfedésben lévő műveletet hajt végre egyetlen szálon, a hívószálnak minden művelethez meg kell adnia egy ÁTFEDÉSBEN lévő struktúrát. Minden ÁTFEDÉSBEN lévő struktúrának meg kell adnia egy leírót egy másik manuális visszaállítási eseményobjektumhoz. Az átfedésben lévő műveletek bármelyikének befejezésére való várakozáshoz a szál az összes manuális visszaállítási eseményt várakozási feltételként határozza meg az egyik többobjektumos várakozási függvény. A többobjektumos várakozási függvény visszatérési értéke azt jelzi, hogy melyik manuális visszaállítási eseményobjektumot jelezték, így a szál meghatározhatja, hogy melyik átfedésben lévő művelet okozta a várakozási műveletet.
Biztonságosabb, ha minden átfedésben lévő művelethez külön eseményobjektumot használ, ahelyett, hogy egyetlen eseményobjektumot sem ad meg, vagy ugyanazt az eseményobjektumot több művelethez is felhasználhatja. Ha a ÁTFEDÉSBEN lévő struktúrában nincs megadva eseményobjektum, a rendszer jelzi a fájl, a nevesített cső vagy kommunikációs eszköz állapotát, ha az átfedésben lévő művelet befejeződött. Így ezeket a fogópontokat szinkronizálási objektumként is megadhatja egy várakozási függvényben, bár az erre a célra való használatuk nehézkes lehet, mivel ha ugyanazon a fájlon, elnevezett csőn vagy kommunikációs eszközön egyidejűleg átfedésben lévő műveleteket hajtanak végre, nem lehet tudni, hogy melyik művelet okozta az objektum állapotának jelzését.
A szálak nem használhatnak újra eseményt azzal a feltételezéssel, hogy az eseményt csak az adott szál átfedésben lévő művelete jelzi. A rendszer egy eseményt ugyanazon a szálon jelez, mint a befejezett átfedésben lévő művelet. Ha ugyanazt az eseményt több szálon használja, az olyan versenyállapothoz vezethet, amelyben az esemény megfelelően van jelezve ahhoz a szálhoz, amelynek a művelete először és idő előtt befejeződik az eseményt használó többi szál esetében. Ezután, amikor a következő átfedésben lévő művelet befejeződik, az eseményt ismét jelzi a rendszer az eseményt használó összes szál esetében, és így tovább, amíg az összes átfedésben lévő művelet be nem fejeződik.
Az átfedésben lévő műveletek, a befejezési rutinok és a GetOverlappedResult függvény használatát bemutató példákért lásd: Csövek használata.
Windows Vista, Windows Server 2003 és Windows XP:
Ügyeljen arra, hogy ÁTFEDÉSBEN lévő struktúrákat újrahasználja. Ha ÁTFEDÉSBEN lévő struktúrák több szálon is újra felhasználhatók, és GetOverlappedResult meghívása a bWait paraméterrel IGAZértékre van állítva, a hívószálnak biztosítania kell a kapcsolódó esemény jelzését a struktúra újbóli használata előtt. Ez a WaitForSingleObject függvénnyel végezhető el, miután meghívta GetOverlappedResult, hogy a szálat a művelet befejezéséig várjon. Vegye figyelembe, hogy az eseményobjektumnak manuális visszaállítású eseményobjektumnak kell lennie. Ha automatikus eseményobjektumot használ, a GetOverlappedResult meghívása a bWait paraméterrel IGAZ, a függvény határozatlan időre le lesz tiltva. Ez a viselkedés a Windows 7-től és a Windows Server 2008 R2-től kezdve megváltozott azon alkalmazások esetében, amelyek a Windows 7-et adják meg támogatott operációs rendszerként az alkalmazásjegyzékben. További információ: alkalmazásjegyzékek.