はじめに
PowerShellで複雑なタスクを効率的に処理するためには、非同期処理が必要になることもあるかも。その時に備えて、Runspaceを使用して非同期処理を実現し、非ジェネリックなHashtableではなく、スレッドセーフなConcurrentDictionaryを使用する方法を解説。
スクリプトの概要
1. RunspacePoolの作成
まず、RunspacePoolを作成して開く。RunspacePoolは、複数のPowerShellインスタンスを効率的に管理するためのオブジェクトである。
1 2 3 4 |
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を作成する。これにより、ジョブとメインスクリプト間で情報を安全に共有できる。
1 2 3 4 5 6 |
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. エコージョブの作成と開始
エコージョブのスクリプトブロックを作成し、バックグラウンドジョブとして実行する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$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. ユーザー入力の受付とジョブとの通信
ユーザーからの入力を受け付け、ジョブに渡してその出力を表示する。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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. 終了処理とリソースのクリーンアップ
スクリプトの終了時にリソースを解放する。
1 2 3 4 5 6 |
Write-Host "スクリプトを終了しています..." -ForegroundColor Magenta $powershell.EndInvoke($handle) $powershell.Dispose() $runspacePool.Close() $runspacePool.Dispose() Write-Host "スクリプトが正常に終了しました。" -ForegroundColor Green |
- リソースのクリーンアップ:
Dispose()
メソッドでリソースを解放する。
まとめ
このスクリプトは、PowerShellで非同期処理を実現するための基本的な方法を示している。RunspaceとConcurrentDictionaryを活用することで、効率的かつ安全に複数のタスクを同時に処理することができる。
コメント