Először csak egy szál

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()



Word To HTML Converter