web-dev-qa-db-ja.com

PowerShellでタスクを並行して実行する

次のようなPowerShellスクリプトがあります。

Foreach ($file in $files) {
    [Do something]
    [Do something]
    [Do something]
}

この方法では、1つのファイルが他のファイルの後に処理されます。 4つのファイルを同時に扱いたい。

私はforeach -parallelループを知っていますが、それはタスクを並行して実行します。基本的に、foreachループ全体を並行して実行したいと思います。

PowerShellでこれを実現するにはどうすればよいですか?

15

Jobs または runspaces を調べることができます。ジョブの例を次に示します。

$block = {
    Param([string] $file)
    "[Do something]"
}
#Remove all jobs
Get-Job | Remove-Job
$MaxThreads = 4
#Start the jobs. Max 4 jobs running simultaneously.
foreach($file in $files){
    While ($(Get-Job -state running).count -ge $MaxThreads){
        Start-Sleep -Milliseconds 3
    }
    Start-Job -Scriptblock $Block -ArgumentList $file
}
#Wait for all jobs to finish.
While ($(Get-Job -State Running).count -gt 0){
    start-sleep 1
}
#Get information from each job.
foreach($job in Get-Job){
    $info= Receive-Job -Id ($job.Id)
}
#Remove all jobs created.
Get-Job | Remove-Job

上記のコードでは、各$fileは互いに並行して実行されています(同時に最大4つまで実行されます)。

編集:コメントへの応答で、 here はスクリプトブロックに関するドキュメントです。パラメーターを含める必要がある理由は、PowerShell関数とは異なり、スクリプトブロックでは中かっこ{}以外のパラメーターを指定できないためです。

23
CuriousOne

Get-Help about_Foreach-Parallel によれば、ForEach -Parallel...は各アイテムに対してスクリプトブロック全体を並列処理しますが、スクリプトブロック内のコマンドは順番に処理されます(括弧で囲まれている場合はおそらく並列化されます) Parallel {...})。ただし、これを受け入れるには、スクリプトがPowerShellワークフローである必要があります。 ParallelおよびSequenceキーワードは、ワークフロー内でのみ有効です。

5
Jeff Zeitlin