PowerShell
Parallel Processing
Command Execution
Scripting
Automation

Can Powershell Run Commands in Parallel?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

PowerShell has become an essential tool for IT professionals and system administrators for automating tasks and managing configurations. One of its powerful features is the ability to run commands in parallel. This significantly boosts efficiency and saves time, especially when managing multiple systems or performing intensive data operations.

Understanding Parallel Execution in PowerShell

Running commands in parallel means executing multiple tasks simultaneously, as opposed to sequentially. This approach can dramatically reduce processing time and improve the throughput of scripts and cmdlets. Starting with PowerShell 7, there is native support for parallel execution through several different mechanisms.

Parallel Execution with ForEach-Object -Parallel

A straightforward way to perform parallel execution is by using the ForEach-Object -Parallel construct. This method is particularly useful when processing collections or arrays where each element can be handled independently.

Syntax

powershell
1$collection | ForEach-Object -Parallel {
2    # Script block to execute in parallel
3    $_ # Represents the current object in the pipeline
4} -ThrottleLimit 5
  • ThrottleLimit: Specifies the maximum number of parallel threads that can run simultaneously. Adjusting this number helps prevent resource exhaustion on the system.

Example

powershell
1$servers = Get-Content -Path "servers.txt"
2$results = $servers | ForEach-Object -Parallel {
3    Test-Connection -ComputerName $_ -Count 1
4} -ThrottleLimit 10
5
6$results | Where-Object { $_.Status -eq 'Success' } | ForEach-Object {
7    Write-Output "$($_.Address) is reachable."
8}

In this example, PowerShell tests connectivity to a list of servers by sending a ping. The task runs up to 10 parallel threads, checking multiple servers simultaneously.

Using Start-Job

PowerShell also allows for parallel execution through jobs. A job is a command that runs in the background without interacting directly with the current session. This is useful for long-running tasks that do not require input during execution.

Syntax

powershell
1$job = Start-Job -ScriptBlock {
2    # Command to execute
3}
4
5# Wait for the job to complete
6Wait-Job -Job $job
7
8# Retrieve the result
9Receive-Job -Job $job

Example

powershell
1$job1 = Start-Job -ScriptBlock { Get-Process }
2$job2 = Start-Job -ScriptBlock { Get-Service }
3
4# Wait for jobs to complete
5Wait-Job -Job $job1, $job2
6
7# Retrieve job results
8$procs = Receive-Job -Job $job1
9$services = Receive-Job -Job $job2
10
11# Display results
12$procs | Select-Object -First 5
13$services | Where-Object { $_.Status -eq 'Running' }

This script starts two background jobs: one to retrieve running processes and another to fetch service statuses. Once the jobs are complete, it retrieves and displays a subset of the results.

Utilizing PowerShell Runspaces

For more advanced scenarios, PowerShell Runspaces provide a high level of control over parallel execution. Runspaces are lightweight instances of the PowerShell runtime that can execute scripts independently of each other. Although more complex to set up, they offer performance benefits and granular management.

Example

powershell
1# Prepare the runspace pool
2$runspacePool = [runspacefactory]::CreateRunspacePool(1, 5)
3$runspacePool.Open()
4
5# Collection of tasks
6$scriptBlocks = 1..10 | ForEach-Object {
7    [powershell]::Create().AddScript({
8        "Task $_ completed"
9    })
10}
11
12# Start each task
13$tasks = @()
14foreach ($ps in $scriptBlocks) {
15    $ps.RunspacePool = $runspacePool
16    $tasks += [PSCustomObject]@{
17        Pipe = $ps
18        Status = $ps.BeginInvoke()
19    }
20}
21
22# Wait for completion
23$tasks | ForEach-Object {
24    $_.Pipe.EndInvoke($_.Status)
25    $_.Pipe.Dispose()
26}
27
28$runspacePool.Close()
29$runspacePool.Dispose()

In this example, we create a pool of runspaces to execute ten independent tasks. Each task writes a message to the output, demonstrating the parallelized execution. The runspacePool determines the number of tasks that can run simultaneously.

Summary Table

Here's a quick reference to parallel execution methods in PowerShell:

MethodDescriptionBest For
ForEach-Object -ParallelNative parallel loop construct for collections from PowerShell 7 onwards.Processing arrays or collections.
Start-JobRuns commands as background jobs.Long-running or independent tasks.
RunspacesOffers fine-grained control and high performance.Advanced scenarios needing custom execution logic.

Conclusion

While sequential execution is sufficient for many tasks, the ability to run commands in parallel opens up new possibilities for improving the performance and responsiveness of your PowerShell scripts. Whether using ForEach-Object -Parallel, background jobs, or runspaces, the choice of method depends on the complexity of the task and the degree of control required. With these techniques, PowerShell becomes an even more potent tool in automating and managing your Windows environment efficiently.


Course illustration
Course illustration

All Rights Reserved.