about_Thread_Jobs
Rövid leírás
Információt nyújt a PowerShell-szálalapú feladatokról. A szálfeladatok olyan háttérfeladatok, amelyek egy parancsot vagy kifejezést futtatnak egy külön szálon az aktuális munkamenet-folyamaton belül.
Hosszú leírás
A PowerShell egyszerre futtat parancsokat és szkripteket a feladatokon keresztül. A PowerShell három feladattípust biztosít az egyidejűség támogatásához.
RemoteJob
- A parancsok és szkriptek távoli munkamenetben futnak. További információ: about_Remote_Jobs.BackgroundJob
– A parancsok és szkriptek külön folyamaton futnak a helyi gépen. További információkért lásd a feladatokat ismertető szakaszt.PSTaskJob
vagyThreadJob
– A parancsok és szkriptek külön szálon futnak ugyanazon a folyamaton belül a helyi gépen.
A szálalapú feladatok nem olyan robusztusak, mint a távoli és a háttérfeladatok, mivel ugyanabban a folyamatban futnak különböző szálakon. Ha egy feladat kritikus hibát jelez, amely összeomlik a folyamat során, akkor a folyamat összes többi feladata leáll.
A szálalapú feladatok azonban kevesebb többletterhelést igényelnek. Nem használják az átnevezési réteget vagy a szerializálást. Az eredményobjektumok az aktuális munkamenetben élő objektumokra mutató hivatkozásokként jelennek meg. E többletterhelés nélkül a szálalapú feladatok gyorsabban futnak, és kevesebb erőforrást használnak, mint a többi feladattípus.
Fontos
A feladatot létrehozó szülő munkamenet is figyeli a feladat állapotát, és összegyűjti a folyamatadatokat. A feladat gyermekfolyamatát a szülőfolyamat leállítja, amint a feladat befejeződött. Ha a szülő munkamenet le van állítva, a rendszer az összes futó gyermekfeladatot leállítja a gyermekfolyamatokkal együtt.
Kétféleképpen lehet megkerülni ezt a helyzetet:
- Leválasztott munkamenetekben futó feladatok létrehozásához használható
Invoke-Command
. További információ: about_Remote_Jobs. - Feladat
Start-Process
helyett új folyamatot hozhat létre. További információ: Start-Process.
Szálalapú feladatok indítása és kezelése
A szálalapú feladatok kétféleképpen indíthatóak el:
Start-ThreadJob
- a ThreadJob modulbólForEach-Object -Parallel -AsJob
- a párhuzamos funkció a PowerShell 7.0-s verzióban lett hozzáadva
A szálalapú feladatok kezeléséhez használja az about_Jobs ismertetett feladatparancsmagokat.
Az Start-ThreadJob
használata
A ThreadJob modult először a PowerShell 6-tal szállították le. A Windows PowerShell 5.1 PowerShell-galéria is telepíthető.
Ha egy szálfeladatot szeretne elindítani a helyi számítógépen, használja a Start-ThreadJob
parancsmagot egy kapcsos zárójelek ({ }
) közé zárt paranccsal vagy szkripttel.
Az alábbi példa elindít egy szálfeladatot, amely parancsot Get-Process
futtat a helyi számítógépen.
Start-ThreadJob -ScriptBlock { Get-Process }
A Start-ThreadJob
parancs egy ThreadJob
, a futó feladatot jelképező objektumot ad vissza. A feladatobjektum hasznos információkat tartalmaz a feladatról, beleértve annak aktuális futó állapotát is. Összegyűjti a feladat eredményeit az eredmények létrehozásakor.
Az ForEach-Object -Parallel -AsJob
használata
A PowerShell 7.0 új paraméterkészletet adott hozzá a ForEach-Object
parancsmaghoz. Az új paraméterek lehetővé teszik a szkriptblokkok párhuzamos szálakban való futtatását PowerShell-feladatokként.
Az adatokat a parancsra helyezheti.ForEach-Object -Parallel
Az adatok a párhuzamosan futó szkriptblokkba kerülnek. A -AsJob
paraméter feladatobjektumokat hoz létre az egyes párhuzamos szálakhoz.
Az alábbi parancs elindít egy feladatot, amely gyermekfeladatokat tartalmaz a parancshoz csövezott minden bemeneti értékhez. Minden gyermekfeladat egy vezetékes bemeneti értékkel futtatja a Write-Output
parancsot argumentumként.
1..5 | ForEach-Object -Parallel { Write-Output $_ } -AsJob
A ForEach-Object -Parallel
parancs egy PSTaskJob
olyan objektumot ad vissza, amely gyermekfeladatokat tartalmaz minden egyes vezetékes bemeneti értékhez. A feladatobjektum hasznos információkat tartalmaz a futó gyermekfeladatokról. Összegyűjti a gyermekfeladatok eredményeit az eredmények létrehozásakor.
A feladatok befejezésére és a feladatok eredményeinek lekérésére való várakozás
A PowerShell-feladat parancsmagjaival például Wait-Job
Receive-Job
megvárhatja, amíg egy feladat befejeződik, majd visszaadhatja a feladat által létrehozott összes eredményt.
A következő parancs elindít egy parancsot futtató Get-Process
szálfeladatot, majd megvárja a parancs befejezését, és végül visszaadja a parancs által generált összes adateredményt.
Start-ThreadJob -ScriptBlock { Get-Process } | Wait-Job | Receive-Job
A következő parancs elindít egy feladatot, amely parancsot Write-Output
futtat minden egyes vezetékes bemenethez, majd megvárja, amíg az összes gyermekfeladat befejeződik, és végül visszaadja a gyermekfeladatok által generált összes adateredményt.
1..5 | ForEach-Object -Parallel { Write-Output $_ } -AsJob | Wait-Job | Receive-Job
A Receive-Job
parancsmag a gyermekfeladatok eredményeit adja vissza.
1
3
2
4
5
Mivel minden gyermekfeladat párhuzamosan fut, a létrehozott eredmények sorrendje nem garantált.
Szálfeladat teljesítménye
A szálfeladatok gyorsabbak és könnyebbek, mint más típusú feladatok. De még mindig vannak olyan többletterheléseik, amelyek nagyok lehetnek, ha összehasonlítják a munkát.
A PowerShell parancsokat és szkripteket futtat egy munkamenetben. Egy munkamenetben egyszerre csak egy parancs vagy szkript futtatható. Így több feladat futtatásakor minden feladat külön munkamenetben fut. Minden munkamenet hozzájárul a többletterheléshez.
A szálfeladatok akkor biztosítják a legjobb teljesítményt, ha az általuk végzett munka nagyobb, mint a feladat futtatásához használt munkamenet többletterhelése. Két eset felel meg ennek a feltételnek.
A munka nagy számítási igényű – A szkriptek több szálas feladaton való futtatása több processzormag előnyeit is kihasználhatja, és gyorsabban elvégezhető.
A munka jelentős várakozásból áll – Egy szkript, amely időt tölt az I/O vagy a távoli hívás eredményeire való várakozással. A párhuzamos futtatás általában gyorsabb, mint ha egymás után fut.
(Measure-Command {
1..1000 | ForEach { Start-ThreadJob { Write-Output "Hello $using:_" } } | Receive-Job -Wait
}).TotalMilliseconds
36860.8226
(Measure-Command {
1..1000 | ForEach-Object { "Hello: $_" }
}).TotalMilliseconds
7.1975
A fenti első példa egy foreach hurkot mutat be, amely 1000 szálfeladatot hoz létre egy egyszerű sztring írásához. A feladat többletterhelése miatt több mint 36 másodpercet vesz igénybe.
A második példa futtatja a ForEach
parancsmagot, hogy ugyanazt az 1000 műveletet hajtsa végre.
Ezúttal ForEach-Object
egymás után, egyetlen szálon fut, feladatterhelés nélkül. Ez 7 ezredmásodpercben fejeződik be.
Az alábbi példában legfeljebb 5000 bejegyzést gyűjtünk össze 10 különálló rendszernaplóhoz. Mivel a szkript több napló olvasását is magában foglalja, érdemes párhuzamosan elvégezni a műveleteket.
$logNames.count
10
Measure-Command {
$logs = $logNames | ForEach-Object {
Get-WinEvent -LogName $_ -MaxEvents 5000 2>$null
}
}
TotalMilliseconds : 252398.4321 (4 minutes 12 seconds)
$logs.Count
50000
A szkript a feladatok párhuzamos futtatásának félidejében fejeződik be.
Measure-Command {
$logs = $logNames | ForEach {
Start-ThreadJob {
Get-WinEvent -LogName $using:_ -MaxEvents 5000 2>$null
} -ThrottleLimit 10
} | Wait-Job | Receive-Job
}
TotalMilliseconds : 115994.3 (1 minute 56 seconds)
$logs.Count
50000
Szálfeladatok és változók
Az értékeket többféleképpen is átadhatja a szálalapú feladatoknak.
Start-ThreadJob
A parancsmagra csövezett, a szkriptblokkba a kulcsszón keresztül $using
átadott vagy az ArgumentList paraméteren keresztül átadott változókat is elfogadhatja.
$msg = "Hello"
$msg | Start-ThreadJob { $input | Write-Output } | Wait-Job | Receive-Job
Start-ThreadJob { Write-Output $using:msg } | Wait-Job | Receive-Job
Start-ThreadJob { param ([string] $message) Write-Output $message } -ArgumentList @($msg) |
Wait-Job | Receive-Job
ForEach-Object -Parallel
Változókba csövezve fogadja el, és a szkriptblokknak közvetlenül a kulcsszón keresztül $using
átadott változókat.
$msg = "Hello"
$msg | ForEach-Object -Parallel { Write-Output $_ } -AsJob | Wait-Job | Receive-Job
1..1 | ForEach-Object -Parallel { Write-Output $using:msg } -AsJob | Wait-Job | Receive-Job
Mivel a szálfeladatok ugyanabban a folyamatban futnak, a feladatba átadott változó referenciatípusokat gondosan kell kezelni. Ha nem szálbiztos objektum, akkor soha nem szabad hozzárendelni, és a metódust és a tulajdonságokat soha nem kell meghívni rajta.
Az alábbi példa egy szálbiztos .NET-objektumot ConcurrentDictionary
ad át az összes gyermekfeladatnak, hogy egyedileg elnevezett folyamatobjektumokat gyűjtsön. Mivel ez egy szálbiztos objektum, biztonságosan használható, miközben a feladatok párhuzamosan futnak a folyamatban.
$threadSafeDictionary = [System.Collections.Concurrent.ConcurrentDictionary[string,object]]::new()
$jobs = Get-Process | ForEach {
Start-ThreadJob {
$proc = $using:_
$dict = $using:threadSafeDictionary
$dict.TryAdd($proc.ProcessName, $proc)
}
}
$jobs | Wait-Job | Receive-Job
$threadSafeDictionary.Count
96
$threadSafeDictionary["pwsh"]
NPM(K) PM(M) WS(M) CPU(s) Id SI ProcessName
------ ----- ----- ------ -- -- -----------
112 108.25 124.43 69.75 16272 1 pwsh