はじめに
PowerShellで複雑なタスクを効率的に処理するためには、非同期処理が必要になることもあるかも。その時に備えて、Runspaceを使用して非同期処理を実現し、非ジェネリックなHashtableではなく、スレッドセーフなConcurrentDictionaryを使用する方法を解説。
スクリプトの概要
1. RunspacePoolの作成
まず、RunspacePoolを作成して開く。RunspacePoolは、複数のPowerShellインスタンスを効率的に管理するためのオブジェクトである。
Write-Host "1. RunspacePoolを作成しています..." -ForegroundColor Yellow $runspacePool = [runspacefactory]::CreateRunspacePool(1, 1) $runspacePool.Open() Write-Host " RunspacePoolが作成され、オープンされました。" -ForegroundColor Green
- RunspacePool: 複数のPowerShellインスタンスを効率的に管理するためのオブジェクト。
CreateRunspacePool(1, 1): 最小1、最大1のRunspaceを持つプールを作成。Open(): RunspacePoolを開き、使用可能にする。
2. 同期Dictionaryの作成
次に、スレッドセーフなConcurrentDictionaryを作成する。これにより、ジョブとメインスクリプト間で情報を安全に共有できる。
Write-Host "2. 同期Dictionaryを作成しています..." -ForegroundColor Yellow $syncDict = [System.Collections.Concurrent.ConcurrentDictionary[string,object]]::new() $syncDict["Input"] = $null $syncDict["Output"] = $null $syncDict["Exit"] = $false Write-Host " 同期Dictionaryが作成されました。" -ForegroundColor Green
- ConcurrentDictionary: スレッドセーフな辞書型コレクション。
syncDict["Input"],syncDict["Output"],syncDict["Exit"]: ジョブとメインスクリプト間で情報を共有するためのキー。
3. エコージョブの作成と開始
エコージョブのスクリプトブロックを作成し、バックグラウンドジョブとして実行する。
$scriptBlock = {
param($syncDict)
while (-not $syncDict["Exit"]) {
if ($syncDict["Input"] -ne $null) {
$syncDict["Output"] = $syncDict["Input"]
$syncDict["Input"] = $null
}
Start-Sleep -Milliseconds 100
}
}
$powershell = [powershell]::Create().AddScript($scriptBlock).AddArgument($syncDict)
$powershell.RunspacePool = $runspacePool
$handle = $powershell.BeginInvoke()
Write-Host "エコージョブが開始されました。入力を待っています..." -ForegroundColor Green
- スクリプトブロック: バックグラウンドジョブとして実行されるコード。
BeginInvoke(): ジョブを非同期で開始。
4. ユーザー入力の受付とジョブとの通信
ユーザーからの入力を受け付け、ジョブに渡してその出力を表示する。
while (-not $syncDict["Exit"]) {
$input = Read-Host "入力してください('exit'で終了)"
if ($input -eq 'exit') {
$syncDict["Exit"] = $true
break
}
$syncDict["Input"] = $input
while ($syncDict["Output"] -eq $null) {
Start-Sleep -Milliseconds 100
}
Write-Host "エコー: $($syncDict["Output"])" -ForegroundColor Yellow
$syncDict["Output"] = $null
}
- ユーザー入力の受付:
Read-Hostでユーザーからの入力を受け付ける。 - ジョブとの通信:
syncDictを通じてジョブに入力を渡し、出力を受け取る。
5. 終了処理とリソースのクリーンアップ
スクリプトの終了時にリソースを解放する。
Write-Host "スクリプトを終了しています..." -ForegroundColor Magenta $powershell.EndInvoke($handle) $powershell.Dispose() $runspacePool.Close() $runspacePool.Dispose() Write-Host "スクリプトが正常に終了しました。" -ForegroundColor Green
- リソースのクリーンアップ:
Dispose()メソッドでリソースを解放する。
まとめ
このスクリプトは、PowerShellで非同期処理を実現するための基本的な方法を示している。RunspaceとConcurrentDictionaryを活用することで、効率的かつ安全に複数のタスクを同時に処理することができる。


コメント