关于多线程:Powershell:Receive-Job中出现意外结果

Powershell: Unexpected results in Receive-Job

我试图更好地了解Powershell如何处理作业。

这些文章均对我们有很大帮助:

  • Powershell中的多线程
  • 将数组传递给Start-Job

但是,使用以下示例脚本,我在调用Receive-Job时得到了意外的结果。我希望每行都有一个结果,但是有时我会看到每行有多个结果或额外的空白回车。关于如何只写出每个作业从控制台流入的信息的任何想法吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$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
2
3
Number is: 1
Number is: 1
Number is: 2

有时...

1
2
3
4
Number is: 1
Number is: 2
Number is: 1Number is: 2
Number is: 1Number is: 2Number is: 2

您过于复杂了。您不需要所有这些循环即可手动处理事物。您应该利用可用的cmdlet。这应该可以实现所需的基础知识:

1
2
3
4
5
6
7
8
9
10
11
12
13
$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的事实意味着您实际上无法访问数据,只是将数据打印到屏幕上。

如果要实际存储或处理结果作业输出,可以执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$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
}