Väntefunktioner
Wait-funktioner tillåta att en tråd blockerar sin egen körning. Väntefunktionerna returneras inte förrän de angivna kriterierna har uppfyllts. Typen av väntefunktion avgör vilken uppsättning kriterier som används. När en väntefunktion anropas kontrollerar den om väntevillkoren har uppfyllts. Om kriterierna inte har uppfyllts anger den anropande tråden väntetillståndet tills villkoren för väntevillkoren har uppfyllts eller det angivna tidsgränsintervallet förflutit.
- Väntefunktioner med ett objekt
- Väntefunktioner för flera objekt
- aviseringsbara väntefunktioner
- registrerade väntefunktioner
- väntar på en adress
- Väntefunktioner och tidsgränsintervall
- Wait Functions och synkroniseringsobjekt
- Wait Functions och Skapa Windows
Väntefunktioner för ett objekt
Funktionerna SignalObjectAndWait, WaitForSingleObjectoch WaitForSingleObjectEx kräver ett handtag till ett synkroniseringsobjekt. Dessa funktioner returneras när något av följande inträffar:
- Det angivna objektet är i signalerat tillstånd.
- Tidsgränsintervallet förflutit. Tidsgränsintervallet kan ställas in på INFINITE- för att ange att väntetiden inte överskrider tidsgränsen.
Funktionen SignalObjectAndWait gör det möjligt för den anropande tråden att atomiskt ange tillståndet för ett objekt som ska signaleras och vänta tills ett annat objekts tillstånd har angetts till signalerat.
Väntefunktioner för flera objekt
Funktionerna WaitForMultipleObjects, WaitForMultipleObjectsEx, MsgWaitForMultipleObjectsoch MsgWaitForMultipleObjectsEx-funktioner gör att den anropande tråden kan ange en matris som innehåller ett eller flera synkroniseringsobjekthandtag. Dessa funktioner returneras när något av följande inträffar:
- Tillståndet för något av de angivna objekten är inställt på signalerat eller tillstånden för alla objekt har angetts till signalerade. Du styr om ett eller alla tillstånd ska användas i funktionsanropet.
- Tidsgränsintervallet förflutit. Tidsgränsintervallet kan ställas in på INFINITE- för att ange att väntetiden inte överskrider tidsgränsen.
Med funktionen MsgWaitForMultipleObjects och MsgWaitForMultipleObjectsEx kan du ange indatahändelseobjekt i objektreferensmatrisen. Detta görs när du anger vilken typ av indata som ska vänta i trådens indatakö. En tråd kan till exempel använda MsgWaitForMultipleObjects för att blockera körningen tills tillståndet för ett angivet objekt har angetts till signalerat och det finns musindata i trådens indatakö. Tråden kan använda funktionen GetMessage eller PeekMessageA eller PeekMessageW för att hämta indata.
När du väntar på att tillstånden för alla objekt ska anges till signalerade ändrar dessa funktioner för flera objekt inte tillstånden för de angivna objekten förrän tillstånden för alla objekt har angetts. Till exempel kan tillståndet för ett mutex-objekt signaleras, men den anropande tråden får inte ägarskap förrän tillstånden för de andra objekten som anges i matrisen också har angetts till signalerade. Under tiden kan någon annan tråd få ägarskap för mutex-objektet och därmed ange dess tillstånd till icke-signalerat.
När du väntar på att tillståndet för ett enskilt objekt ska vara inställt på signal kontrollerar dessa funktioner för flera objekt handtagen i matrisen i ordning från index 0 tills ett av objekten signaleras. Om flera objekt signaleras returnerar funktionen indexet för det första handtaget i matrisen vars objekt signalerades.
Aviseringsbara väntefunktioner
MsgWaitForMultipleObjectsEx, SignalObjectAndWait, WaitForMultipleObjectsExoch WaitForSingleObjectEx funktioner skiljer sig från de andra väntefunktionerna genom att de kan utföra en aviseringsbar väntetidsåtgärd. I en aviseringsbar vänteåtgärd kan funktionen returneras när de angivna villkoren uppfylls, men den kan också returneras om systemet köar en I/O-slutföranderutin eller en APC för körning av den väntande tråden. Mer information om aviseringsbara vänteåtgärder och I/O-slutföranderutiner finns i Synkronisering och Överlappande indata och utdata. Mer information om API:er finns i Asynkrona proceduranrop.
Registrerade väntefunktioner
Funktionen RegisterWaitForSingleObject skiljer sig från de andra väntefunktionerna eftersom vänteåtgärden utförs av en tråd från trådpoolen. När de angivna villkoren uppfylls körs återanropsfunktionen av en arbetstråd från trådpoolen.
Som standard är en registrerad vänteåtgärd en åtgärd med flera väntetider. Systemet återställer timern varje gång händelsen signaleras (eller tidsgränsintervallet förflutit) tills du anropar funktionen UnregisterWaitEx för att avbryta åtgärden. Ange att en vänteåtgärd bara ska köras en gång genom att ange dwFlags parametern för RegisterWaitForSingleObject till WT_EXECUTEONLYONCE.
Om tråden anropar funktioner som använder API:er anger du parametern dwFlags för RegisterWaitForSingleObject till WT_EXECUTEINPERSISTENTTHREAD.
Väntar på en adress
En tråd kan använda funktionen WaitOnAddress för att vänta tills värdet för en måladress ändras från något oönskat värde till något annat värde. Detta gör att trådar kan vänta tills ett värde ändras utan att behöva snurra eller hantera de synkroniseringsproblem som kan uppstå när tråden fångar ett oönskat värde men värdet ändras innan tråden kan vänta.
WaitOnAddress returnerar när kod som ändrar målvärdet signalerar ändringen genom att anropa WakeByAddressSingle för att aktivera en enda väntande tråd eller WakeByAddressAll för att aktivera alla väntande trådar. Om ett tidsgränsintervall anges med WaitOnAddress och ingen tråd anropar en aktiveringsfunktion, returnerar funktionen när tidsgränsintervallet förflutit. Om inget tidsgränsintervall har angetts väntar tråden på obestämd tid.
Väntefunktioner och tidsgränsintervall
Noggrannheten för det angivna tidsgränsintervallet beror på systemklockans upplösning. Systemklockan "tickar" i konstant takt. Om tidsgränsintervallet är mindre än systemklockans upplösning kan väntetiden överskrida den angivna tidsperioden. Om tidsgränsintervallet är större än en tick men mindre än två kan väntetiden vara någonstans mellan en och två tick och så vidare.
Om du vill öka noggrannheten för tidsgränsintervallet för väntefunktionerna anropar du funktionen timeGetDevCaps för att fastställa den minsta timermatchning som stöds och funktionen timeBeginPeriod för att ange timerupplösningen till sitt minimum. Var försiktig när du anropar timeBeginPeriodeftersom frekventa anrop avsevärt kan påverka systemklockan, systemets energianvändning och schemaläggaren. Om du anropar timeBeginPeriodanropar du det en gång tidigt i programmet och ska anropa funktionen timeEndPeriod i slutet av programmet.
Väntefunktioner och synkroniseringsobjekt
Väntefunktionerna kan ändra tillstånden för vissa typer av synkroniseringsobjekt. Ändring sker endast för objektet eller objekt vars signaltillstånd gjorde att funktionen returnerades. Wait-funktioner kan ändra tillstånden för synkroniseringsobjekt på följande sätt:
- Antalet semaforobjekt minskar med en, och semaforens tillstånd är inställt på nonsignaled om antalet är noll.
- Tillstånden för mutex-, automatisk återställningshändelse och ändringsmeddelandeobjekt anges till icke-signalerade.
- Tillståndet för en synkroniseringstimer är inställt på nonsignaled.
- Tillstånden för manuell återställningshändelse, timer för manuell återställning, process-, tråd- och konsolindataobjekt påverkas inte av en väntefunktion.
Wait Functions och skapa Windows
Du måste vara försiktig när du använder väntefunktionerna och koden som direkt eller indirekt skapar fönster. Om en tråd skapar några fönster måste den bearbeta meddelanden. Meddelandesändningar skickas till alla fönster i systemet. Om du har en tråd som använder en väntefunktion utan tidsgränsintervall kommer systemet att blockeras. Två exempel på kod som indirekt skapar fönster är DDE och funktionen CoInitialize. Om du har en tråd som skapar fönster använder du därför MsgWaitForMultipleObjects eller MsgWaitForMultipleObjectsExi stället för de andra väntefunktionerna.