Foreach-Object -Parallel Counter

Hi,
How to a use a counter variable inside for the foreach-object -parallel?
Something like:
$i=0
1…10 | ForEach-Object -parallel {$I++; Write-host $i}

It does not work. What’s wrong?
Thanks.

Check your version of Powershell. The documentation claims -Parallel was introduced in PS 7.

Assuming your on the correct version of powershell… ‘Does not work’ does not tell us anything. Do you get errors?

I defined the $i=0 prior to the foreach and the value does not change in the loop.
I am using POSH v7.2.6
Thanks.

The variable you define outside of the foreach-object will not be known in the runspaces. They are like remote sessions, variables can be referenced with $using: modifier, but afaik can’t be updated. The object you pass in (in this case 1..10) will be available to the runspace as $_

$i = 48
1..10 | ForEach-Object -parallel {
    Write-Host "This number won't change $($using:i)"
    Write-Host "But this number is passed in $_" -ForegroundColor Cyan
}

The reason you were seeing the number 1 output previously is a blank variable with ++ is equal to 1. You can try it without runspaces. Make up a variable and watch

$doesntexist++
Write-Host $doesntexist

In each loop you were basically defining local $i = 1

1 Like

Great! We are getting closer.
What I really need is to have a counter inside the foreach loop when I open a file and go thru it in the loop and the counter will show me the progress.
Like:
$i=0
Get-content MyFile.txt | ForEach-Object - Parallel {$_ ;Write-host $i}
Thanks.

Might want to have a look at Write-Progress

Great idea but the issue persists with using write-progress: a counter needs to be increased within that foreach-object -Parallel loop.

I think I found the secret for using “imported” variables inside a ForEach-Object - Parallel loop at: ForEach-Object (Microsoft.PowerShell.Core) - PowerShell | Microsoft Docs - Example # 14

Ahh very good, you’ve jogged my memory. Here’s a slightly simpler example than 14

$hash = [hashtable]::Synchronized(@{})

$hash.I = 0

1..10 | ForEach-Object -parallel {
    $hash = $using:hash
    $hash.I++
    
    Write-host $hash.I
}

image

The trick is to assign the synchronized variable to a local variable and then it will handle updating the original across threads.