1

Code works interactively, in a PS1 file it does not. to reproduce, open powershell, paste the function and then run get-job to see the task. type get-job | remove-job when done and then put code in a PS1 file, it only runs the first two, then exits.

function RunJobFromQueue
{

    if( $queue.Count -gt 0)

    {
        $cn = $queue.Dequeue()

        $j = Start-Job -name $cn -ScriptBlock {param($x); Start-Sleep -Seconds 10;"output - " + $x} -ArgumentList $cn

        Register-ObjectEvent -InputObject $j -EventName StateChanged -Action {RunJobFromQueue; Unregister-Event $eventsubscriber.SourceIdentifier; Remove-Job $eventsubscriber.SourceIdentifier } | Out-Null
    }

}

$maxConcurrentJobs = 2
$jobInput = "test1", "test2", "test3", "test4", "test5", "test6"
$queue = [System.Collections.Queue]::Synchronized( (New-Object System.Collections.Queue) )
foreach($item in $jobInput) {$queue.Enqueue($item)}

for( $i = 0; $i -lt $maxConcurrentJobs; $i++){RunJobFromQueue}

1 Answer 1

4

In my opinion: it fails in script because:

  • you start script, define function and variables in script scope
  • script exits once it defines 2 initial jobs
  • job complete, registered action runs, but your function is not visible to it (defined in script scope) so it fails.

Two options to solve/ work around it:

  • define RunJobFromQueue function in global scope (function Global:RunJobFromQueue, $global:queue)
  • dot-source a script (. .\YourScript.ps1)

This works fine interactively, because in that case you define function/ variable in global scope, so -Action can find them just fine.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.