Posted on Leave a comment

Multi threading in powershell

Multi threading can save you a lot of time when you process multiple multiple jobs at the same time. Powershell is a very advanced scripting tool and there are a lot of things that can be implemented with it. As a result in many occasions you will need to do things in parallel so that you have a quicker execution.

Lets examine a simple scenario on how we can use multi threading on powershell. We will use the Test-Connection method which sends ICMP echo request packets, or pings, to one or more computers. We will use the below three domains and we will try to execute a test connection to all of them.

$computers = @("","","")

In order to calculate the time that this operation needs we will use the StopWatch class.

$watch = New-Object System.Diagnostics.Stopwatch; 
foreach ($item in $computers) { test-connection $item; }; 
echo "Elapsed time:" $watch.Elapsed.TotalSeconds;

The total Elapsed Time for this operation to complete would be around 10 seconds by performing the actions serially.

Lets examine how could we could use multi threading in order to complete this operation faster. In powershell v7 you can use the ForEach-Object with Parallel parameter. An example can be found below. This operation will be executed in parallel by multiple threads.

$watch = New-Object System.Diagnostics.Stopwatch;  
$computers | ForEach-Object -Parallel {test-connection $_} -AsJob | Receive-Job -Wait ; 
echo "Elapsed time:" $watch.Elapsed.TotalSeconds;

The result for this execution would be 3.8 seconds which means that we have 6 seconds less execution time or about 2.5 times faster.

If we use powershell v5 we can implement multi threading with the Start-Job. By using that we will need to write our logic inside the ScriptBlock.

$watch = New-Object System.Diagnostics.Stopwatch; 
$job1 = Start-Job -ScriptBlock { test-connection -ComputerName "" }
$job2 = Start-Job -ScriptBlock { test-connection -ComputerName "" }
$job3 = Start-Job -ScriptBlock { test-connection -ComputerName "" }

Get-Job | Wait-Job

Receive-Job $job1
Receive-Job $job2
Receive-Job $job3

echo "Elapsed time:" $watch.Elapsed.TotalSeconds;

As we can see the execution time is about 3,9 seconds which is close enough with the time of powershell 7 script.

Youtube video: