Most lépjünk a következő szintre! Legyen több szálunk párhuzamosan, méghozzá „óvatosan”, azaz egy időben csak először mondjuk 5 szálunk fusson, a többi legyen várakozó állásponton. Nézzük az ezt demonstráló példaszkriptet:
$ScriptBlock = {
param($length,$id)
Start-Sleep $length
"`tKész
$id : $length sec"
}
$maxthread = 5
$rp = [runspacefactory]::CreateRunspacePool(1, $maxthread)
$rp.Open()
$jobs = New-Object System.Collections.ArrayList
function Get-Results {
param([switch]$wait)
$start = Get-Date
do {
$hasdata = $false
foreach($job in $jobs) {
$futás = if($job.job.iscompleted
-eq $null){"megszűntetve"}
elseif($job.job.iscompleted){"befejezte"}
else{"fut"}
Write-Host
"JobID: $($job.id), hossz:
$($job.hossz), fut: $futás" -ForegroundColor Green
if ($job.job.isCompleted)
{
$job.powershell.EndInvoke($job.job)
$job.powershell.dispose()
$job.job = $null
$job.powershell = $null
}
elseif ($job.job -ne $null) {
$hasdata = $true
}
}
if ($hasdata -and $wait)
{
$eltelt = "{0:n2}" -f ((get-date) - $start).totalseconds
"$eltelt másodperc ----------------------------------"
Start-Sleep
-Milliseconds 1000
}
} while ($hasdata -and $wait)
}
cls
1..7 | %{
$hossz = Get-Random 4
$p = [powershell]::Create().AddScript($ScriptBlock).AddArgument($hossz).AddArgument($_)
$p.RunspacePool = $rp
$rv = New-Object -TypeName PSObject -Property @{
PowerShell = $p
Job = $p.BeginInvoke()
id = $_
hossz = $hossz
}
[void]$jobs.Add($rv)
}
"Előkészítettem
a feladatokat"
Get-Results -wait
$rp.Close()
Az elején van az a $scriptblock, amit párhuzamosan fogok futtatni sok szálon, ami tulajdonképpen egy neki átadott szám hosszan várakozik, majd kiírja, hogy ő kész. A $maxthread hordozza, hogy mennyi legyen az egy időben futó szálak száma. A párhuzamosításhoz egy RunspacePool-t, azaz futási terület-készletet hozok létre, ez hordozza azt az információt, hogy hány darab párhuzamos szálat engedek. Ezután Tobiastól átvett Get-Results függvényt definiálom, ami egy nagyon ügyes függvény, ciklikusan vizsgálja a szálakat tartalmazó tömböt, és amelyik befejeződött, annak a visszatérési értékét kiteszi a kimenetre és utána kitakarítja a szál maradványait. Én ezt még megfejeltem egy kis kiíratással is, hogy lássuk, hogy pontosan hol is tartanak a szálak.
Ezután jön a tényleges többszálúságot demonstráló rész. Összesen 7 feladatot hozok létre egy kis ciklusban rendre a $p változóban, amiben meghatározom, hogy a korábban létrehozott RunspacePool-ba illeszkedjen, azaz sorolódjon be a korábban létrehozott párhuzamosságot szabályozó feltétel rendeszerbe.
Hogy könnyebb legyen ezt a $p szálat és az egyéb diagnosztikai adatokat berakni a $jobs tömbbe, amit aztán a Get-Results meg tud jeleníteni, ehhez hozom létre a $rv egyedi objektumot.
Ha a sok feladatot létrehoztam, utána már csak a Get-Results segítségével várakozó üzemmódban figyelem az eredményeket, amelyek így néznek ki első nekifutásra:
Előkészítettem a feladatokat
JobID: 1,
hossz: 2, fut: fut
JobID: 2,
hossz: 0, fut: befejezte
Kész 2 : 0 sec
JobID: 3,
hossz: 3, fut: fut
JobID: 4,
hossz: 2, fut: fut
JobID: 5,
hossz: 1, fut: fut
JobID: 6,
hossz: 1, fut: fut
JobID: 7,
hossz: 1, fut: fut
0,02 másodperc ----------------------------------
JobID: 1,
hossz: 2, fut: fut
JobID: 2,
hossz: 0, fut: megszűntetve
JobID: 3,
hossz: 3, fut: fut
JobID: 4,
hossz: 2, fut: fut
JobID: 5,
hossz: 1, fut: befejezte
Kész 5 : 1 sec
JobID: 6,
hossz: 1, fut: befejezte
Kész 6 : 1 sec
JobID: 7,
hossz: 1, fut: fut
1,06 másodperc ----------------------------------
JobID: 1,
hossz: 2, fut: befejezte
Kész 1 : 2 sec
JobID: 2,
hossz: 0, fut: megszűntetve
JobID: 3,
hossz: 3, fut: fut
JobID: 4,
hossz: 2, fut: befejezte
Kész 4 : 2 sec
JobID: 5,
hossz: 1, fut: megszűntetve
JobID: 6,
hossz: 1, fut: megszűntetve
JobID: 7,
hossz: 1, fut: befejezte
Kész 7 : 1 sec
2,12 másodperc ----------------------------------
JobID: 1,
hossz: 2, fut: megszűntetve
JobID: 2,
hossz: 0, fut: megszűntetve
JobID: 3,
hossz: 3, fut: befejezte
Kész 3 : 3 sec
JobID: 4,
hossz: 2, fut: megszűntetve
JobID: 5,
hossz: 1, fut: megszűntetve
JobID: 6,
hossz: 1, fut: megszűntetve
JobID: 7,
hossz: 1, fut: megszűntetve
Mit is látunk itt? A 7 feladat közül a 2-es azonosítójú rögtön be is fejeződött, hiszen 0 ideig tartó várakozást kapott a Get-Random cmdlettől. Ez volt az első etap. A második etapban, 1,06 másodperc elteltével befejeződött az 5-ös és 6-os feladat, mindkettő 1 másodperces várakozást kapott. Vegyük észre, hogy a 7-es sorszámú, bár ő is 1 másodperces késleltetést kapott mégsem ért véget, hiszen ő még várakozott, nem fért bele az 5-ös készletbe. A következő etapban már ő is befejeződött és még a 2 másodperces 1-es és 4-es szálak is. A végén meg a 3-as is befejeződött. Azaz tetten értük (több oldalnyi unalmas kimenet idemásolása nélkül J), hogy tényleg késleltetésre volt ítélve egy szál.
Nézzük, mi van akkor, ha megnövelem a szálak számát, mondjuk 7-re:
Előkészítettem a feladatokat
JobID: 1,
hossz: 1, fut: fut
JobID: 2,
hossz: 2, fut: fut
JobID: 3, hossz:
2, fut: fut
JobID: 4,
hossz: 0, fut: befejezte
Kész 4 : 0 sec
JobID: 5,
hossz: 3, fut: fut
JobID: 6,
hossz: 3, fut: fut
JobID: 7,
hossz: 2, fut: fut
0,03 másodperc ----------------------------------
JobID: 1,
hossz: 1, fut: befejezte
Kész 1 : 1 sec
JobID: 2,
hossz: 2, fut: fut
JobID: 3,
hossz: 2, fut: fut
JobID: 4,
hossz: 0, fut: megszűntetve
JobID: 5,
hossz: 3, fut: fut
JobID: 6,
hossz: 3, fut: fut
JobID: 7,
hossz: 2, fut: fut
1,08 másodperc ----------------------------------
JobID: 1,
hossz: 1, fut: megszűntetve
JobID: 2,
hossz: 2, fut: befejezte
Kész 2 : 2 sec
JobID: 3,
hossz: 2, fut: befejezte
Kész 3 : 2 sec
JobID: 4,
hossz: 0, fut: megszűntetve
JobID: 5,
hossz: 3, fut: fut
JobID: 6,
hossz: 3, fut: fut
JobID: 7,
hossz: 2, fut: befejezte
Kész 7 : 2 sec
2,12 másodperc ----------------------------------
JobID: 1,
hossz: 1, fut: megszűntetve
JobID: 2,
hossz: 2, fut: megszűntetve
JobID: 3,
hossz: 2, fut: megszűntetve
JobID: 4,
hossz: 0, fut: megszűntetve
JobID: 5,
hossz: 3, fut: befejezte
Kész 5 : 3 sec
JobID: 6,
hossz: 3, fut: befejezte
Kész 6 : 3 sec
JobID: 7,
hossz: 2, fut: megszűntetve
Itt most semmi trükk nincs, minden szál a neki megadott várakozás után ért véget. Annak felderítését, hogy mi történne, ha mondjuk, csak 2 párhuzamos szálat engednénk a tisztelt olvasóra bízom.