Chapters/scripting-at-scale/scaling-backgroundjobs.ps1


#create a big list of names from whatever list you want to use
$computers = 1..5 | foreach {get-content C:\scripts\servers.txt}


#using nothing 52 sec
#85 items 4:45
measure-command { 
 $all = foreach ($item in $computers) {
    test-wsman $item
}
}

#using background jobs 56 sec
#85 items 4:32
measure-command {
$all=@()
$all+= foreach ($item in $computers) {
 start-job {test-wsman $item}
}
$all | Wait-job | receive-job -Keep
}

#basic runspace
$run = [powershell]::Create()
$run.AddCommand("test-wsman").addparameter("computername",$env:computername)
$handle = $run.beginInvoke()
$results = $run.EndInvoke($handle)
$run.Dispose()

#using runspaces 10sec
#85 items 16 seconds
measure-Command {
#initialize an array to hold runspaces
$rspace = @()

#create a runspace for each computer
foreach ($item in $computers) {
    $run = [powershell]::Create()
    $run.AddCommand("test-wsman").addparameter("computername",$item)
    $handle = $run.beginInvoke()
    #add the handle as a property to make it easier to reference later
    $run | Add-member -MemberType NoteProperty -Name Handle -Value $handle
    $rspace+=$run
}

<# alternative
While ($rspace.invocationStateInfo.state -contains "running") {
 #loop and wait
}
#>


While (-Not $rspace.handle.isCompleted) {
    #an empty loop waiting for everything to complete
}

#get results
$results=@()
for ($i = 0;$i -lt $rspace.count;$i++) {
    $results+= $rspace[$i].EndInvoke($rspace[$i].handle)
}

#cleanup
$rspace.ForEach({$_.dispose()})

}