Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
En trådpool är en samling arbetstrådar som effektivt kör asynkrona återanrop för programmets räkning. Trådpoolen används främst för att minska antalet programtrådar och tillhandahålla hantering av arbetstrådarna. Program kan köa arbetsobjekt, associera arbete med väntebara referenser, automatiskt köa baserat på en timer och binda med I/O.
Arkitektur för trådpool
Följande program kan dra nytta av att använda en trådpool:
- Ett program som är mycket parallellt och kan skicka ett stort antal små arbetsobjekt asynkront (till exempel distribuerad indexsökning eller nätverks-I/O).
- Ett program som skapar och förstör ett stort antal trådar som körs under en kort tid. Med hjälp av trådpoolen kan du minska komplexiteten i trådhantering och de kostnader som krävs för att skapa och förstöra trådar.
- Ett program som bearbetar oberoende arbetsobjekt i bakgrunden och parallellt (till exempel att läsa in flera flikar).
- Ett program som måste utföra en exklusiv väntan på kernelobjekt eller blockera inkommande händelser på ett objekt. Att använda trådpoolen kan minska komplexiteten i trådhantering och öka prestandan genom att minska antalet kontextväxlar.
- En applikation som skapar anpassade trådar för väntan på händelser.
Den ursprungliga trådpoolen har omarbetats helt i Windows Vista. Den nya trådpoolen har förbättrats eftersom den har en enda arbetstrådstyp (stöder både I/O och icke-I/O), inte använder en timertråd, tillhandahåller en enda timerkö och tillhandahåller en dedikerad beständig tråd. Det ger också rensningsgrupper, högre prestanda, flera pooler per process som schemaläggs separat och ett nytt trådpools-API.
Trådpoolarkitekturen består av följande:
- Arbetartrådar som kör återanropsfunktionerna
- Servitörtrådar som väntar på flera väntehandtag
- En arbetskö
- En standardtrådspool för varje process
- En worker-fabrik som hanterar worker-trådarna
Metodtips
Det nya trådpools-API:et ger mer flexibilitet och kontroll än ursprungliga. Det finns dock några subtila men viktiga skillnader. I det ursprungliga API:et var vänteåterställningen automatisk. i det nya API:et måste väntan uttryckligen återställas varje gång. Det ursprungliga API:et hanterade personifiering automatiskt och överför säkerhetskontexten för anropsprocessen till tråden. Med det nya API:et måste programmet uttryckligen ange säkerhetskontexten.
Följande är metodtips när du använder en trådpool:
Trådarna i en process delar trådpoolen. En enskild arbetstråd kan köra flera återanropsfunktioner, en i taget. Dessa arbetstrådar hanteras av trådpoolen. Avsluta därför inte en tråd från trådpoolen genom att anropa TerminateThread i tråden eller genom att anropa ExitThread från en återanropsfunktion.
En I/O-begäran kan köras på valfri tråd i trådpoolen. Att avbryta I/O i en trådpoolstråd kräver synkronisering eftersom funktionen avbryt kan köras på en annan tråd än den som hanterar I/O-begäran, vilket kan leda till att en okänd åtgärd avbryts. Undvik detta genom att alltid ange den OVERLAPPED- struktur som en I/O-begäran initierades med när CancelIoEx- anropas för asynkron I/O, eller använd din egen synkronisering för att säkerställa att inga andra I/O kan startas i måltråden innan du anropar antingen funktionen CancelSynchronousIo eller CancelIoEx.
Rensa alla resurser som skapats i återanropsfunktionen innan du återvänder från funktionen. Dessa omfattar TLS, säkerhetskontexter, trådprioritet och COM-registrering. Återanropsfunktioner måste också återställa trådtillståndet innan de returnerar.
Håll väntehandtagen och deras associerade objekt vid liv tills trådpoolen har signalerat att den är klar med handtaget.
Markera alla trådar som väntar på långa åtgärder (till exempel I/O-tömningar eller resursrensning) så att trådpoolen kan allokera nya trådar i stället för att vänta på den här.
Innan du tar bort en DLL som använder trådpoolen avbryter du alla arbetsobjekt, I/O, vänteåtgärder och timers och väntar tills återanropen har körts.
Undvik dödlägen genom att eliminera beroenden mellan arbetsobjekt och mellan återanrop, genom att se till att ett återanrop inte väntar på att det självt ska slutföras, och genom att bevara trådprioriteten.
Lägg inte för många objekt i kö alltför snabbt i en process med andra komponenter som använder standardtrådspoolen. Det finns en standardtrådspool per process, inklusive Svchost.exe. Som standard har varje trådpool högst 500 arbetstrådar. Trådpoolen försöker skapa fler arbetstrådar när antalet arbetstrådar i tillståndet redo/körs måste vara mindre än antalet processorer.
Undvik COM:s single-threaded apartment-modell, eftersom den är inkompatibel med trådpoolen. STA skapar trådtillstånd som kan påverka nästa arbetsobjekt för tråden. STA är vanligtvis långvarig och knuten till en viss tråd, till skillnad från trådpoolen.
Skapa en ny trådpool för att styra trådprioritet och isolering, skapa anpassade egenskaper och eventuellt förbättra svarstiden. Ytterligare trådpooler kräver dock fler systemresurser (trådar, kernelminne). För många pooler ökar risken för CPU-konkurrens.
Använd om möjligt ett väntebart objekt i stället för en APC-baserad mekanism för att signalera en trådpoolstråd. APC:er fungerar inte lika bra tillsammans med trådpoolstrådar som andra signalmekanismer, eftersom systemet styr livslängden för trådpoolstrådar, så en tråd kan avslutas innan aviseringen levereras.
Använd felsökningstillägget för trådpoolen, !tp. Det här kommandot har följande användning:
- pool adressflaggor
- obj adressflaggor
- tqueue adressflaggor
- servitör adress
- arbetsadress
För pool, servitör och arbetare, om adressen är noll, dumpar kommandot alla objekt. För servitör och arbetare dumpar utelämnande av adressen den aktuella tråden. Följande flaggor definieras: 0x1 (enradsutdata), 0x2 (dumpmedlemmar) och 0x4 (dumppoolens arbetskö).
Note
Moderna alternativ: För C++/WinRT-program är den Windows trådpoolen tillgänglig via coroutines – använd co_await winrt::resume_background() för att skicka arbete till trådpoolen och co_await winrt::resume_foreground(dispatcher) för att återgå till användargränssnittstråden. Detta ger strukturerad samtidighet utan manuell återanropshantering. För standard-C++-kod erbjuder std::async med policyn std::launch::async portabel uppgiftsbaserad parallellism, även om den inte använder Windows-trådpoolen direkt.
Relaterade ämnen