Legyen több szál

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ételrendeszerbe.

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ésleteté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.



Word To HTML Converter