System Worker-trådar

En drivrutin som kräver fördröjd bearbetning kan använda ett arbetsobjekt som innehåller en pekare till en rutin för återanrop av drivrutin som utför den faktiska bearbetningen. Drivrutinen köar arbetsobjektet och en systemarbetstråd tar bort arbetsobjektet från kön och kör drivrutinens återanropsrutin. Systemet har en pool med dessa systemarbetaretrådar, som är systemtrådar som var och en bearbetar ett arbetsobjekt i taget.

Drivrutinen associerar en WorkItem-återanropsrutin med arbetsobjektet. När systemarbetaretråden bearbetar arbetsobjektet anropas den associerade WorkItem-rutinen . I Windows Vista och senare versioner av Windows kan en drivrutin i stället associera en WorkItemEx-rutin med ett arbetsobjekt. WorkItemEx tar parametrar som skiljer sig från de parametrar som WorkItem tar.

WorkItem - och WorkItemEx-rutiner körs i en systemtrådskontext. Om en drivrutin kan köras i en trådkontext i användarläge kan den rutinen anropa en WorkItem - eller WorkItemEx-rutin för att utföra åtgärder som kräver en systemtrådskontext.

För att använda ett arbetsobjekt utför en drivrutin följande steg:

  1. Allokera och initiera ett nytt arbetsobjekt.

    Systemet använder en IO_WORKITEM struktur för att lagra ett arbetsobjekt. Om du vill allokera en ny IO_WORKITEM struktur och initiera den som ett arbetsobjekt kan drivrutinen anropa IoAllocateWorkItem. I Windows Vista och senare versioner av Windows kan drivrutinen också allokera sin egen IO_WORKITEM struktur och anropa IoInitializeWorkItem för att initiera strukturen som ett arbetsobjekt. (Drivrutinen bör anropa IoSizeofWorkItem för att fastställa antalet byte som krävs för att lagra ett arbetsobjekt.)

  2. Associera en återanropsrutin med arbetsobjektet och köa arbetsobjektet så att det bearbetas av en systemarbetstråd.

    Om du vill associera en WorkItem-rutin med arbetsobjektet och köa arbetsobjektet ska drivrutinen anropa IoQueueWorkItem. Om du i stället vill associera en WorkItemEx-rutin med arbetsobjektet och köa arbetsobjektet ska drivrutinen anropa IoQueueWorkItemEx.

  3. När arbetsobjektet inte längre krävs frigör du det.

    Ett arbetsobjekt som har allokerats av IoAllocateWorkItem bör frigöras av IoFreeWorkItem. Ett arbetsobjekt som initierades av IoInitializeWorkItem måste vara onitialiserat av IoUninitializeWorkItem innan det kan frigöras.

    Arbetsuppgiften kan bara vara oinitierad eller frigjord när den inte är i kö. Systemet tar bort arbetsobjektet innan det anropar arbetsobjektets återanropsrutin, så IoFreeWorkItem och IoUninitializeWorkItem kan anropas inifrån återanropet.

En DPC som behöver initiera en bearbetningsaktivitet som kräver lång bearbetning eller som gör ett blockerande anrop bör delegera bearbetningen av uppgiften till ett eller flera arbetsobjekt. När en DPC körs hindras alla trådar från att köras. Dessutom får en DPC, som körs på IRQL = DISPATCH_LEVEL, inte göra blockeringsanrop. Dock körs systemets arbetstråd som bearbetar ett arbetsobjekt på IRQL = PASSIVE_LEVEL. Arbetsobjektet kan därför innehålla blockeringsanrop. En systemarbetartråd kan till exempel vänta på ett dispatcher-objekt.

Eftersom poolen med systemarbetstrådar är en begränsad resurs kan WorkItem - och WorkItemEx-rutiner endast användas för åtgärder som tar en kort tid. Om någon av dessa rutiner körs för länge (om den till exempel innehåller en obestämd loop) eller väntar för länge kan systemet blockeras. Om en drivrutin kräver långa perioder av fördröjd bearbetning bör den därför i stället anropa PsCreateSystemThread för att skapa en egen systemtråd.

Anropa inte IoQueueWorkItem eller IoQueueWorkItemEx för att köa ett arbetsobjekt som redan finns i kön. Om du gör det kan systemdatastrukturer skadas. Om din drivrutin köar samma arbetsobjekt varje gång en viss drivrutinsrutin körs kan du använda följande teknik för att undvika att arbetsobjektet köas igen om detta redan finns i kön.

  • Drivrutinen har en lista över uppgifter för arbetsrutinen.
  • Den här uppgiftslistan är tillgänglig i den kontext som tillhandahålls till arbetsrutinen. Arbetsrutinen och eventuella drivrutinsrutiner som ändrar uppgiftslistan synkroniserar deras åtkomst till listan.
  • Varje gång arbetsrutinen körs utför den alla uppgifter i listan och tar bort varje uppgift från listan när uppgiften har slutförts.
  • När en ny uppgift kommer lägger drivrutinen till den här uppgiften i listan. Drivrutinen köar arbetsobjektet endast om aktivitetslistan tidigare var tom.

System worker-tråden tar bort arbetsobjektet från kön innan det anropar arbetstråden. Därför kan en drivrutinstråd på ett säkert sätt köa arbetsobjektet igen så snart arbetstråden börjar köras.