Nézzük mindennek az alkatrészeit, kezdjük egy thread (szál) objektummal. Mivel a PowerShell processzben vagyunk, ezért ennek egy szála a [PowerShell] osztály egy újabb példánya:
$thread = [powershell]::create()
Ez így még elég csupasz, adjunk át neki egy egyszerű kis szkriptet, amit majd végre tudunk később hajtani. Azért, hogy rögtön a paraméterátadást is meg lehessen nézni, rögtön egy olyan szkriptet nézzünk, amiben paraméter is szerepel:
$script = {
param($adat)
"Adat: $adat"
for($i = 0; $i -lt $adat; $i++){
Start-Sleep 1
"i: $i"
}
}
A szkript az átadott $adat paraméternek megfelelő ideig egy ciklusban másodpercenként kiírja az éppen aktuális ciklusváltozót.
Tegyük akkor ezt bele a szálunkba és adjunk is értéket a paraméternek:
$thread = $thread.AddScript($script)
$thread = $thread.AddArgument(30)
Ha ezután megnézzük a $thread változót, nem sok minden látszik rajta az átadott adatokat illetően, viszont sok egyéb adatra fény derül:
[6] PS C:\> $thread
Commands : System.Management.Automation.PSCommand
Streams : System.Management.Automation.PSDataStreams
InstanceId : ea1f2743-958c-4434-b55e-e23618dad153
InvocationStateInfo : System.Management.Automation.PSInvocationStateInfo
IsNested : False
Runspace : System.Management.Automation.Runspaces.LocalRunspace
RunspacePool :
Nézzük meg ennek az objektumnak a metódusait is:
[7] PS C:\> $thread | gm -MemberType methods
TypeName: System.Management.Automation.PowerShell
Name MemberType Definition
---- ---------- ----------
AddArgument Method powershell AddArgument(System.Object value)
AddCommand Method powershell AddCommand(string cmdlet), pow...
AddParameter Method powershell AddParameter(string parameterN...
AddParameters Method powershell AddParameters(System.Collectio...
AddScript Method powershell AddScript(string script), powe...
BeginInvoke Method System.IAsyncResult BeginInvoke(), System...
BeginStop Method System.IAsyncResult BeginStop(System.Asyn...
CreateNestedPowerShell Method powershell CreateNestedPowerShell()
Dispose Method System.Void Dispose()
EndInvoke Method System.Management.Automation.PSDataCollec...
EndStop Method System.Void EndStop(System.IAsyncResult a...
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
Invoke Method System.Collections.ObjectModel.Collection...
Stop Method System.Void Stop()
ToString Method string ToString()
Az eddig látott Add… metódusok mellett van még az Invoke és a Stop metódus. Ezeket nem nagyon érdemes használni, hiszen ez az Invoke hasonlóan működik, mintha egy Start-Job –wait kifejezéssel futtatnánk egy háttérfolyamatot, azaz a többszálúság előnyei nem igazán jönnek elő. Ennek leállítására van a Stop metódus.
Az igazi futtatási mód a BeginInvoke lesz. Vigyázni kell, hogy ilyenkor tényleg egy külön szállal lesz dolgunk, így ahhoz, hogy ezzel kapcsolatban maradjuk és a kimenetét meg tudjuk nézni, a BeginInvoke futtatása után visszaadott „fogantyút” el kell kapni:
$handle = $thread.BeginInvoke()
Ha ezt az objektumot megnézzük, akkor ennek tulajdonságai élő kapcsolatban vannak a háttérben futószállal, így például az állapotáról az IsCompleted tulajdonság tájékoztat minket:
[10] PS C:\> $handle
CompletedSynchronou IsCompleted AsyncState AsyncWaitHandle
sly
------------------- ----------- ---------- ---------------
False False System.Threadin...
Ha már kész:
[11] PS C:\> $handle.IsCompleted
True
Akkor kiolvashatjuk az elkészült kimenetet:
[12] PS C:\> $thread.EndInvoke($handle)
Adat: 30
i: 0
i: 1
i: 2
…
i: 28
i: 29
Érdemes lehet ellenőrizni, hogy nem történt-e hiba a végrehajtás során, hiszen ez a szál nincsen szerves kapcsolatban az őt elindító környezettel, így a hibákat sem adja át magától. Sőt! Például a write-host cmdlet nincsen ebben a szálban, így ezt nem használhatjuk, ha mégis, akkor a következő tulajdonságból a hiba kiolvasható (a következő kimenet az eredeti szkript kicsit módosított változata után jön elő, amiben szerepel write-host is):
[31] PS C:\> $thread.Streams
Error : {Cannot invoke this function because the current host does not impl
ement it.}
Progress : {}
Verbose : {}
Debug : {}
Warning : {}
[32] PS C:\> $thread.Streams.Error
Write-Host : Cannot invoke this function because the current
host does not imp
lement it.
At line:3 char:11
+ Write-Host <<<< "Adat: $adat"
+
CategoryInfo : NotImplemented:
(:) [Write-Host], HostException
+
FullyQualifiedErrorId : HostFunctionNotImplemented,Microsoft.PowerShell
.Commands.WriteHostCommand
Ha az egész szálra már nincs szükség, akkor a Dispose metódussal eltakaríthatjuk:
[34] PS C:\> $thread.Dispose()