2012-10-07 5 views
15

Ich bin nicht sicher auszuführen, ob dies für Multi-Threading ein Bedarf aufrufen, Job-basierte oder Asynchron, aber im Grunde habe ich ein Skript Powershell-Funktion, die mehrere Parameter und I nimmt müssen sie mehrmals mit unterschiedlichen Parametern aufrufen und diese parallel laufen lassen.Wie ein Powershell-Funktion mehrmals parallel

Derzeit rufe ich die Funktion wie folgt aus:

Execute "param1" "param2" "param3" "param4" 

Wie kann ich diese mehrmals aufrufen für jeden Anruf, ohne warten Rückkehr an den Anrufer Execute?

v2.0 Ich laufe Zeit, aber ich kann, wenn

EDIT notwendig aktualisieren: hier ist was ich bisher habe, was nicht funktioniert:

$cmd = { 
    param($vmxFilePath,$machineName,$username,$password,$scriptTpath,$scriptFile,$uacDismissScript,$snapshotName) 
    Execute $vmxFilePath $machineName $username $password $scriptTpath $scriptFile $uacDismissScript $snapshotName 
} 

Start-Job -ScriptBlock $cmd -ArgumentList $vmxFilePath, $machineName, $username $password, $scriptTpath, $scriptFile, $uacDismissScript, $snapshotName 

ich einen Fehler:

EDIT2: Ich habe mein Skript geändert, aber ich bekomme immer noch den oben genannten Fehler. Hier ist mein mod:

$cmd = { 
    param($vmxFilePath,$machineName,$username,$password,$scriptTpath,$scriptFile,$uacDismissScript,$snapshotName) 
    Execute $vmxFilePath $machineName $username $password $scriptTpath $scriptFile $uacDismissScript $snapshotName 
} 

Start-Job -ScriptBlock $cmd -ArgumentList $vmxFilePath, $machineName, $username $password, $scriptTpath, $scriptFile, $uacDismissScript, $snapshotName 

Antwort

29

Kein Update notwendig für diese. Definieren Sie einen Skriptblock und verwenden Sie Start-Job, um den Skriptblock so oft wie nötig auszuführen. Beispiel:

$cmd = { 
    param($a, $b) 
    Write-Host $a $b 
} 

$foo = "foo" 

1..5 | ForEach-Object { 
    Start-Job -ScriptBlock $cmd -ArgumentList $_, $foo 
} 

Der Skriptblock dauert 2 Parameter $a und $b, die durch die -ArgumentList Option übergeben werden. In dem obigen Beispiel sind die Zuordnungen $_$a und $foo$b. $foo ist nur ein Beispiel für einen konfigurierbaren, aber statischen Parameter.

Führen Sie Get-Job | Remove-Job irgendwann aus, um die beendeten Jobs aus der Warteschlange zu entfernen (oder Get-Job | % { Receive-Job $_.Id; Remove-Job $_.Id }, wenn Sie die Ausgabe abrufen möchten).

+0

Ich bin immer noch eine harte Zeit Abbildung Ihre Lösung mit meinem eigenen Skript zu arbeiten. Ich beginne einfach zu starten und versuche einfach Start-Job zu bekommen, um meinen Skriptblock mit den Argumenten auszuführen, die meine benutzerdefinierte Funktion Execute benötigt. Vielleicht kannst du erweitern? Ist $ foo ein Parameter zusätzlich zu den Parametern param ($ a, $ b)? – JohnZaj

+0

Ich sehe jetzt, danke. Ich bekomme trotzdem den Fehler. Wenn Sie nicht sicher sind, was das sein könnte, werde ich nur separate Post/Frage erstellen. – JohnZaj

+0

Ersetzen Sie zu Testzwecken den Aufruf Ihrer 'Execute()' -Funktion mit Code, der nur die Parameter wiedergibt. Funktioniert es? Wenn dies der Fall ist, liegt das Problem bei der Funktion, die Sie aufrufen möchten. –

16

Hier ist eine schnelle Scheinskript zum Zwecke der Prüfung:

$Code = { 
    param ($init) 
    $start = Get-Date 
    (1..30) | % { Start-Sleep -Seconds 1; $init +=1 } 
    $stop = Get-Date 
    Write-Output "Counted from $($init - 30) until $init in $($stop - $start)." 
} 

Diese Skript kann dann beispielsweise mit 3 Parametern (10, 15, 35)

$jobs = @() 
(10,15,35) | % { $jobs += Start-Job -ArgumentList $_ -ScriptBlock $Code } 

Wait-Job -Job $jobs | Out-Null 
Receive-Job -Job $jobs 
zu Start-Job, übergeben werden

Dies erstellt 3 Jobs, weist sie der Variablen $jobs zu, führt sie parallel aus und wartet dann, bis diese 3 Jobs abgeschlossen sind, und ruft die Ergebnisse ab:

Diese
Counted from 10 until 40 in 00:00:30.0147167. 
Counted from 15 until 45 in 00:00:30.0057163. 
Counted from 35 until 65 in 00:00:30.0067163. 

dauerte 90 Sekunden nicht, nur auszuführen 30.

Einer der kniffligen Teile ist -Argumentlist zu Start-Job, zur Verfügung zu stellen und verfügen über einen param() Block innerhalb des Script. Ansonsten werden Ihre Werte vom Skriptblock nie gesehen.

3

Es tut mir leid, dass jeder Ihre Ausgabe verpasst - ich weiß, es ist viel zu spät, aber ...

Dieser Fehler wird verursacht, weil Sie ein Komma zwischen $ username und $ password in Ihrer Liste vermissen.

Sie können es mit diesem Code-Schnipsel testen, die ich aus der früheren Antworten modelliert:

$cmd = { 
    param($a, $b, $c, $d) 
} 
$foo = "foo" 
$bar = "bar" 
start-job -scriptblock $cmd -ArgumentList "a", $foo, $bar, "gold" #added missing comma for this to work 
2

Sie können eine Alternative benutzen, die als Aufruf Aufträge schneller sein kann, wenn die Funktion nicht lange läuft ein . Max Thread ist 25 und ich habe diese Funktion nur 10 Mal aufgerufen, also erwarte ich eine Gesamtlaufzeit von 5 Sekunden. Sie können Measure-Command um die Anweisung 'results =' wickeln, um Statistiken anzuzeigen.

Beispiel:

$ScriptBlock = { 
     Param ([int]$RunNumber) 

     Start-Sleep -Seconds 5 
     Return $RunNumber 

    } 



    $runNumbers = @(1..10) 


    $MaxThreads = 25 
    $runspacePool = [RunspaceFactory ]::CreateRunspacePool(1, $MaxThreads) 
    $runspacePool.Open() 


    $pipeLines = foreach($num in $runNumbers){ 

           $pipeline = [powershell]::Create() 
           $pipeline.RunspacePool = $runspacePool 
           $pipeline.AddScript($ScriptBlock) | Out-Null 
           $pipeline.AddArgument($num) | Out-Null 

           $pipeline | Add-Member -MemberType NoteProperty -Name 'AsyncResult' -Value $pipeline.BeginInvoke() -PassThru 
        } 



    #obtain results as they come. 
    $results = foreach($pipeline in $pipeLines){ 
         $pipeline.EndInvoke($pipeline.AsyncResult) 
       } 


    #cleanup code. 
    $pipeLines | % { $_.Dispose()} 
    $pipeLines = $null 
    if ($runspacePool) { $runspacePool.Close()} 

    #your results 
    $results