PowerShell Runspace Pools
A runspace pool is a set of runspaces that share out many tasks. It reuses a small set of runspaces instead of making a new one for each task.
One task runs from a pool
A pool is opened, then one task is linked to it. EndInvoke collects the single result.
$pool = [runspacefactory]::CreateRunspacePool(1, 2)
$pool.Open()
$ps = [powershell]::Create()
$ps.RunspacePool = $pool
[void]$ps.AddScript('param($x) $x * 2').AddParameter("x", 21)
$async = $ps.BeginInvoke()
$r = $ps.EndInvoke($async)
"Pool task: $r"
$ps.Dispose()
$pool.Close()
$pool.Dispose()Several tasks share one pool
Each task starts without waiting for the others. Sorting the collected results gives a fixed order.
$pool = [runspacefactory]::CreateRunspacePool(1, 3)
$pool.Open()
$powers = @()
$asyncs = @()
foreach ($n in 1..3) {
$ps = [powershell]::Create()
$ps.RunspacePool = $pool
[void]$ps.AddScript('param($x) $x * 10').AddParameter("x", $n)
$powers += $ps
$asyncs += $ps.BeginInvoke()
}
$out = @()
for ($i = 0; $i -lt $powers.Count; $i++) { $out += $powers[$i].EndInvoke($asyncs[$i]); $powers[$i].Dispose() }
"Pool tasks: " + (($out | Sort-Object) -join ", ")
$pool.Close()
$pool.Dispose()A pool is reused for a second task
The same pool stays open after the first task ends. A second task runs from it without a new pool.
$pool = [runspacefactory]::CreateRunspacePool(1, 2)
$pool.Open()
$ps = [powershell]::Create()
$ps.RunspacePool = $pool
[void]$ps.AddScript('param($x) $x * 2').AddParameter("x", 5)
$async = $ps.BeginInvoke()
$r1 = $ps.EndInvoke($async)
$ps.Dispose()
$ps2 = [powershell]::Create()
$ps2.RunspacePool = $pool
[void]$ps2.AddScript('param($x) $x * 2').AddParameter("x", 7)
$async2 = $ps2.BeginInvoke()
$r2 = $ps2.EndInvoke($async2)
$ps2.Dispose()
"Reuse: $r1, $r2"
$pool.Close()
$pool.Dispose()Example
$pool = [runspacefactory]::CreateRunspacePool(1, 3)
$pool.Open()
$powers = @()
$asyncs = @()
foreach ($n in 1..4) {
$ps = [powershell]::Create()
$ps.RunspacePool = $pool
[void]$ps.AddScript('param($x) $x * 10').AddParameter("x", $n)
$powers += $ps
$asyncs += $ps.BeginInvoke()
}
$out = @()
for ($i = 0; $i -lt $powers.Count; $i++) { $out += $powers[$i].EndInvoke($asyncs[$i]); $powers[$i].Dispose() }
"Pool results: " + (($out | Sort-Object) -join ", ")
$pool.Close()
$pool.Dispose()Key points
- Runspace pool: a set of runspaces that share out many tasks.
- Use CreateRunspacePool to make a pool with a smallest and largest size.
- Use Open to start the pool before any task runs.
- Use BeginInvoke to start each task without waiting for it.
- Use EndInvoke to collect each finished task result.
- Use Sort-Object on collected results because tasks finish in no fixed order.
In this example, a pool of up to three runspaces is opened first. Four tasks are started from it, and each result is collected in turn. Sorting gives a fixed printed order, then the pool is closed and disposed.
Note
Close and Dispose clean up the pool after every task is collected.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Why use a pool instead of one runspace per task?