Using Runspace pool and doing multithreading to run multiple jobs in windows PowerShell without exhausting the system resource.

In my previous posts below, I have talked about how to Use runspace in windows powershell to run powershell scripts in the background and then we saw how we can pass on the argument using for parameters used in our script, today we will see how we can do multi-threading in using runspace to run multiple jobs in background.

If you would like to check my first 2 post on using runspace please find their link below.


Runspace also gives us ability to throttle no of jobs will be running at a time, we can create multiple runsapce job and invoke them, but if we wish to run some certain no of jobs only, we can restrict the same as well, pending jobs will be running once the jobs in current pool finishes.

Like you submitted 50 jobs, but only wish to run 25 jobs at a time, you can restrict the runspace pool to run jobs and rest of the jobs will start as soon as the jobs in the current pool finishes.

For Creating multiple Thread we will be creating run space pool using the “[runspacefactory]::CreateRunspacePool()”

#Create runspace pool and assign 10 no of jobs to run concurrently.
$RunspacePool = [runspacefactory]::CreateRunspacePool(1,10)
$RunspacePool.Open()

Now Let’s first create our sample script to run multiple background Runspace jobs.
So here we have list of Process Name for which we wish to get the currently running process on the system.

$ProcessNameList = "WmiPrvSE","chrome","svchost"
 
$ScriptBlock={
param ($ProcessName)
get-process | ? {$_.ProcessName -eq $processName }
}

Create an empty Array to save Job information

$jobs=@()

Now we will run the foreach loop to create a separate job for each process name.

foreach ($processName in $ProcessNameList) {
#creating a runspace job
$Job = [System.Management.Automation.PowerShell]::Create()
$Job = $job.AddScript($scriptBlock)
$Job = $job.AddArgument($processName)
$Job.RunspacePool = $RunspacePool
 
# We will create a PSO object to save job information and result.
 
$Jobs+=New-Object PSObject -Property @{                               
                                Pipe=$Job
                              Result = $Job.BeginInvoke()
                }
}

Now we can monitor the job status by Recalling the  $jobs Array.


Once all the jobs are Completed we can get the result out from the jobs using the below scripts, in the script below we just simply doing endinvoke() method for each jobs in the $jobs array and savings the result in $results Array.

$Results=@()
ForEach ($Job in $Jobs)
   {
            $Pipe = $Job | Select -Expand Pipe
            $Result = $Job | Select -Expand Result
            $Results += $Pipe.EndInvoke($Result)
   }

Now we recall $results array on PowerShell we can see that data from all 3 jobs at once place, isn’t that cool, this could be helpful where you need to achieve grater results in short span of time.


I hope you like my post, your comments and feedback are welcome on comments sections.

Next I will do some post on couple of Office 365 and Exchange script to generate the environment and various reports wish usually takes long time.

Comments