そもそもジョブとは何?
コマンドをバックグラウンドで実行するとき、PowerShellでは、「ジョブ」オブジェクトを使って、バックグラウンド実行を表現する。コマンドをバックグラウンド実行すると、ジョブオブジェクトが作られ、このオブジェクトに対して操作を行うことで、実行を停止させる、あるいは状態を調べることができる。ジョブの状態はStateプロパティが表わす。
Stateプロパティを確認するにはGet-Jobコマンドを使う。なお、バックグラウンドジョブは、停止させることは可能だが、中断させることや停止したジョブを再開させることはできない。Running、Completed以外の場合、実行が失敗あるいは他の理由でバックグラウンドジョブは停止している。再実行させるには同じStart-Jobコマンドを実行するしかない。
バックグラウンド演算子やStart-Jobコマンドで起動するジョブを「Background Job」という。これは複数あるPowerShellジョブの1つだ。
そのほか、WorkflowやCIMJobなどもあるが、特定目的のオブジェクト処理に関するものであり、ここでは解説しない。スケジュールジョブは、タスクスケジューラーのタスクをPowerShellのジョブとして扱うものだ。ここでは、バックグラウンドジョブとスレッドジョブのみを扱う。
ジョブは、実行中のPowerShellとは別プロセスで起動されるため、ジョブコマンドからは実行中のPowerShellにある変数や関数などにアクセスできない。同様にジョブコマンド側で変数に定義しても、PowerShell側に持ち込むこともできない。
関数定義や変数へのアクセスが必要になる場合、-InitializationScriptオプションや-ArgumentListオプションを使って必要な情報を渡す。-InitializationScriptオプションを使うと、ジョブコマンドで利用できる関数を定義することができる。
Start-Job -InitializationScript {function mydir($x){ Get-ChildItem $x }} { mydir "D:\temp" }
-ArgumentListオプションを使うことで、ジョブコマンドに引数を与えることができる。
ただし、スクリプトブロック内でParmステートメントを使って受け取る引数を定義しておく必要がある。
$mypath="D:\temp"
start-job -ScriptBlock { param($p); dir $p } -ArgumentList $mypath
実行結果を受け取る場合には、ジョブコマンドは代入文とせず実行するだけにしてReceive-Jobコマンドの出力を変数に代入する。ただし、-keepオプションを付けないで実行するとその時点の実行結果は消えてしまう。これは、長い実行時間の間に散発的に出力を行うようなコマンドの場合、-keepオプションを付けないReceive-Jobを繰り返すことで最新の出力のみを受け取り可能にするためだ。
Start-Job -ScriptBlock { dir }
$r=Receive-Job -id <ジョブID>
バックグラウンドジョブが終了し、結果も受け取って用済みとなったときには、Remove-Jobで削除することができる。すべてのジョブを削除したいときには、
Get-Job | Remove-Job
とする。
スレッドジョブ
スレッドジョブは、現在のPowerShellと同じプロセス内で、スレッドとして実行される。バックグラウンドジョブは、別プロセスを起動するため起動に時間がかかり、メモリなどのリソースを消費する。大量のジョブを並列実行させたときには、起動時間のオーバーヘッドが大きくなる。
スレッドジョブは、プロセスを生成しないので高速に起動する。しかし、スレッドジョブはジョブコマンド側のエラーが実行中のPowerShellに影響を与える可能性があり、最悪、ジョブコマンドとともにクラッシュする可能性がある。
速度を取るか、安全性を取るかといった問題だが、単純な外部コマンドなどの実行であれば、起動のオーバーヘットはそれほど問題にならないので、わざわざスレッドジョブを使う必要はないだろう。スレッドジョブは、クラッシュする危険がないコマンドを大量に並行実行させるときに使う。
スレッドジョブは、起動にStart-ThreadJobコマンド(https://learn.microsoft.com/ja-jp/powershell/module/threadjob/start-threadjob)を用いる以外は、バックグラウンドジョブと同じで、他のバックグラウンドジョブ用のコマンド(Get-Jobなど)をそのまま使う。また、起動オプションに関しても共通して使えるものがある。
ただし、PowerShell環境としては分離されている(PowerShellのRunspaceを使っている)ため、バックグラウンドジョブと同じく、実行中のPowerShellで定義した関数や変数をジョブコマンドで直接利用できない。Start-Jobと同じく-InitializationScriptオプションや、-ArgumentListオプションを使って必要な情報を渡す。
かなり時間のかかるUpdate-Helpコマンド(https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/update-help)などもバックグラウンドで処理すれば終了を待つ必要もない。
PowerShellのバックグラウンド実行には制限も多いが、内部コマンドだけ、あるいは外部コマンドなら、あまり気にする必要はない。自作の関数があるときや変数でパラメーターを指定しているときのみ注意すればよい。

この連載の記事
-
第508回
PC
Scalable Vector Graphics(SVG)そもそも何なのか? -
第507回
PC
Windows 11の「開発者モード」とは何か? -
第506回
PC
Windows 11は早くも来秋登場の26H2プレビューの準備が始まる -
第505回
PC
結構変化しているWindows 11のエクスプローラーの基本設定を見直す -
第504回
PC
新しいOutlookとOutlook Classic、そろそろ古いOutlookとExchangeの組み合わせは引退の頃合いか -
第503回
PC
機能が増えたこともあり、寄せ集めから統合化に進むWindowsの便利ツール「PowerToys」 -
第502回
PC
Windows 11でBluetoothのオーディオ新規格「Bluetooth LE Audio」を試す -
第501回
PC
Windows 11 Ver.25H2での変更点、新機能を整理する -
第500回
PC
Windows 11 Ver.25H2が完成した -
第499回
PC
Windowsでの致命的だが回復可能なエラーに備える手段を2つ紹介 -
第498回
PC
Windows Terminalの安定版V1.23が公開 設定UIが改良される - この連載の一覧へ















