Powershell multiple threading headache

Soldato
Joined
8 Mar 2005
Posts
3,676
Location
London, UK
I have almost got the following code to work as expected;

Code:
Param($ScriptFile = 'C:\local_apps\ctx_xd_check\ps_get-ll.ps1',
    $ComputerList = 'C:\local_apps\ctx_xd_check\machines2.txt',
    $MaxThreads = 50,
    $SleepTimer = 8000,
    $MaxWaitAtEnd = 600,
    $OutputType = "Gridview")
    
$Computers = Get-Content $ComputerList
 
 
"Killing existing jobs . . ."
Get-Job | Remove-Job -Force
"Done."
 
$i = 0
 
ForEach ($Computer in $Computers){
    While ($(Get-Job -state running).count -ge $MaxThreads){
        Write-Progress  -Activity "Creating Server List" -Status "Waiting for threads to close" -CurrentOperation "$i threads created - $($(Get-Job -state running).count) threads open" -PercentComplete ($i / $Computers.count * 100) Start-Sleep -Milliseconds $SleepTimer
    }
 
"Starting job - $Computer"
    $i++
    Start-Job -FilePath $ScriptFile -ArgumentList $Computer -Name $Computer | Out-Null
    Write-Progress  -Activity "Creating Server List" -Status "Starting Threads" -CurrentOperation "$i threads created - $($(Get-Job -state running).count) threads open" -PercentComplete ($i / $Computers.count * 100)
    
}
 
$Complete = Get-date
 
While ($(Get-Job -State Running).count -gt 0){
    $ComputersStillRunning = ""
    ForEach ($System  in $(Get-Job -state running)){$ComputersStillRunning += ", $($System.name)"}
    $ComputersStillRunning = $ComputersStillRunning.Substring(2)
    Write-Progress  -Activity "Creating Server List" -Status "$($(Get-Job -State Running).count) threads remaining" -CurrentOperation "$ComputersStillRunning" -PercentComplete ($(Get-Job -State Completed).count / $(Get-Job).count * 100)
    If ($(New-TimeSpan $Complete $(Get-Date)).totalseconds -ge $MaxWaitAtEnd){"Killing all jobs still running . . .";Get-Job -State Running | Remove-Job -Force}
    Start-Sleep -Milliseconds $SleepTimer
}
 
"Reading all jobs"
 
If ($OutputType -eq "Text"){
    ForEach($Job in Get-Job){
        "$($Job.Name)"
        "****************************************"
        Receive-Job $Job #| Select-Object * -ExcludeProperty RunspaceId #| Export-CSV 'N:\scripts\powershell\test3.csv'  -NoTypeInformation
        " "
    }
}
ElseIf($OutputType -eq "Gridview"){
#    Get-Job | Receive-Job | Select-Object * -ExcludeProperty RunspaceId | Export-CSV 'N:\scripts\powershell\test.csv'  -NoTypeInformation
#    Get-Job | Receive-Job | Select-Object * -ExcludeProperty RunspaceId | Export-CSV '\\ukz527\vc$\vbs\scripts\powershell\PS-Multi\PSmulti-Output.csv'  -NoTypeInformation
    Get-Job | Receive-Job | Select-Object * -ExcludeProperty RunspaceId | ConvertTo-Csv -NoTypeInformation | % {$_.Replace('"','')} | Out-File 'C:\local_apps\ctx_xd_check\LL-Output.csv' 
}

This pulls a server list and then executes a secondary script again each server. However as soon as it hits the thread limit (50 in this case), instead of the expected sleep/check logic kicking it throws out the following error message;

Code:
Write-Progress : Cannot bind parameter 'Id'. Cannot convert value "Start-Sleep"
 to type "System.Int32". Error: "Input string was not in a correct format."
At C:\local_apps\ctx_xd_check\psmulti.ps1:19 char:23
+         Write-Progress <<<<   -Activity "Creating Server List" -Status "Waiti
ng for threads to close" -CurrentOperation "$i threads created - $($(Get-Job -s
tate running).count) threads open" -PercentComplete ($i / $Computers.count * 10
0) Start-Sleep -Milliseconds $SleepTimer
    + CategoryInfo          : InvalidArgument: (:) [Write-Progress], Parameter
   BindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerSh
   ell.Commands.WriteProgressCommand

Until the thread count drops below 50, at which point it restarts threads until it again hits 50 and throws out the same errors etc until it completes. the export works fine, albeit with considerably less rows of data than expected.

Would appreciate any pointers.

Cheers, Paul.
 
Soldato
OP
Joined
8 Mar 2005
Posts
3,676
Location
London, UK
So at this point;
Code:
 While ($(Get-Job -state running).count -ge $MaxThreads){
        Write-Progress  -Activity "Creating Server List" -Status "Waiting for threads to close" -CurrentOperation "$i threads created - $($(Get-Job -state running).count) threads open" -PercentComplete ($i / $Computers.count * 100) Start-Sleep -Milliseconds $SleepTimer
    }

Not sure I fully understand. This should loop until it drops below MaxThreads at which point it starts additional threads.

Hmm.
 
Associate
Joined
3 Apr 2007
Posts
1,719
Location
London
I agree with azteched, it looks like you need to move the...

Start-Sleep -Milliseconds $SleepTimer

... command onto a new line. At the moment it is part of your write-progress command and it is that that is giving the error as it doesn't know what to do with it.

Your error....

Write-Progress : Cannot bind parameter 'Id'. Cannot convert value "Start-Sleep"
to type "System.Int32". Error: "Input string was not in a correct format."

Checking the help for write-progress shows...

-Id <int>
Specifies an ID that distinguishes each progress bar from the others. Use this parameter when you are creating
more than one progress bar in a single command. If the progress bars do not have different IDs, they are super
mposed instead of being displayed in a series.

Required? false
Position? 3
Default value
Accept pipeline input? false
Accept wildcard characters? false

Your sleep command is the third parameter on your write-progress line, where it is expecting an int, so it is trying to convert the sleep command, which it sees as a string not a command, to a int and failing.
 
Back
Top Bottom