Powershell: неожиданные результаты при приеме на работу

Я пытаюсь лучше понять, как powershell справляется с заданиями.

Обе эти статьи очень помогли:

Однако в следующем примере сценария я получаю неожиданные результаты при вызове Receive-Job. Я ожидаю результат в каждой строке, но иногда я вижу несколько результатов в каждой строке или дополнительные пустые возвраты каретки. Любая идея о том, как записать только информацию, которая поступает из консоли с каждой работы?

$loops = 1..10
$jobs = new-object System.Collections.ArrayList

$loops | % {
    $jobs.add( 
        (start-job -ScriptBlock {
            param($list)
            $list | % {
                sleep -seconds (get-random -Maximum 3 -Minimum 1)
                write-host "Number is: $_"
            }
        } -ArgumentList (,$loops))
    ) | out-null
}


while ($jobs.count -gt 0)
{
    if ($jobs -ne $null)
    {
        $list = $jobs | ? { $_.HasMoreData -eq $true }
        $list | % { Receive-Job -Job $_ }
        $list2 = $jobs.Clone() | ? { $_.State -eq "Completed" }
        $list2 | % {
            $jobs.Remove($_) | out-null
        }
        $list = $null
    }
}

Вывод может быть...

Количество: 1
Количество: 1
Количество: 2

Или иногда...

Количество: 1
Количество: 2
Количество: 1 Количество: 2
Номер: 1Количество: 2Количество: 2

1 ответ

Решение

Вы сильно усложняете это. Вам не нужны все эти циклы, чтобы обрабатывать вещи вручную. Вы должны воспользоваться доступными вам командлетами. Это должно достичь основ того, что вы хотите:

$loops = 1..10

$scriptBlock = {
  param($list)
  $list | % {
    sleep -seconds (get-random -Maximum 3 -Minimum 1)
    write-host "Number is: $_"
  }
}

$jobs = $loops | % { start-job -ScriptBlock $scriptBlock -ArgumentList (,$loops) }

$jobs | Wait-Job | Receive-Job

Тем не менее, это сгруппирует весь вывод вместе без какого-либо способа узнать, что за работа и что сделала. И тот факт, что вы используете Write-Host означает, что вы не можете получить доступ к данным, они просто выводятся на экран.

Если вы хотите на самом деле сохранить или обработать полученный результат работы, вы можете сделать что-то вроде этого:

$loops = 1..10

$scriptBlock = {
  param($list)
  $list | % {
    sleep -seconds (get-random -Maximum 3 -Minimum 1)
    "Number is: $_"  # don't use write-host, just output the string
  }
}

$jobs = $loops | % { start-job -ScriptBlock $scriptBlock -ArgumentList (,$loops) }

$jobs | Wait-Job  # wait for all jobs to be complete
$jobs |%{
   $output = $_ | Receive-Job
   # process $output here, do what you want with it
}
Другие вопросы по тегам