Search code examples
powershelljobs

Increment a variable in a job


I want to increment a variable in a PowerShell job with a number defined before the job starts.

I tried with a global variable but it didn't work, so now I try to write in a file and load it in my job but that didn't work either. I summarize my loop:

$increment = 1
$Job_Nb = 1..3

foreach ($nb in $Job_Nb) {
    $increment > "C:\increment.txt"

    Start-Job -Name $nb -ScriptBlock {
        $increment_job = Get-Content -Path "C:\increment.txt"
        $increment_job
    }

    $increment++
}

I want my 2 variables $increment_job and $increment to be equal. I obtain the good result with the command Wait-Job, like that:

$increment = 1
$Job_Nb = 1..3

foreach ($nb in $Job_Nb) {
    $increment > "C:\increment.txt"

    Start-Job -Name $nb -ScriptBlock {
        $increment_job = Get-Content -Path "C:\increment.txt"
        $increment_job
    } | Wait-Job | Receive-Job

    $increment++
}

But I can't wait each job to finish before starting the next, it's too long... I need to execute a lot of jobs in the background.

For me, even $nb, $increment and $increment_job can be equal.

If it can help you to understand, a really simple way to put it:

$nb = 1
$Job_Nb = 1..3
foreach ($nb in $Job_Nb) {
    Start-Job -Name $nb -ScriptBlock {$nb}
    $nb++
}

Solution

  • If you want the two variables to be equal, you can just pass $increment into your script block as an argument.

    # Configure the Jobs
    $increment = 1
    $Job_Nb = 1..3
    
    Foreach ($nb in $Job_Nb) {
    
        Start-Job -Name $nb -ScriptBlock {
          $increment_job = $args[0]
          $increment_job
        } -ArgumentList $increment
    
    $increment++
    }
    
    # Retrieve the Jobs After Waiting For All to Complete
    Wait-Job -Name $job_nb | Receive-Job
    

    The problem with your initial approach as you have discovered is that PowerShell processes the entire loop before a single job completes. Therefore, the job doesn't read the increment.txt file until after its contents are set to 3.

    Passing values into the -ArgumentList parameter of a script block without a parameter block will automatically assign the arguments to the $args array. Space delimited arguments will each become an element of the array. A value not space-separated can simply be retrieved as $args or $args[0] with the difference being $args will return a type of Object[] and $args[0] will return the type of the data you passed into it.

    Obviously, you do not need to wait for all jobs to complete. You can just use Get-Job to retrieve whichever jobs you want at any time.