Multithreading Powershell:接收作业中出现意外结果
我正试图更好地了解powershell如何处理作业 这两篇文章都帮了大忙:Multithreading Powershell:接收作业中出现意外结果,multithreading,powershell,start-job,powershell-jobs,Multithreading,Powershell,Start Job,Powershell Jobs,我正试图更好地了解powershell如何处理作业 这两篇文章都帮了大忙: 但是,在下面的示例脚本中,我在调用Receive Job时得到了意外的结果。我希望每行都有一个结果,但有时我会看到每行都有多个结果或额外的空白回车。有没有关于如何只写出从每个作业的控制台流入的信息的想法 $loops = 1..10 $jobs = new-object System.Collections.ArrayList $loops | % { $jobs.add( (star
$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
}
}
输出可以是
Number is: 1
Number is: 1
Number is: 2
电话号码是:1
电话号码是:1
电话号码是:2
或者有时候
Number is: 1
Number is: 2
Number is: 1Number is: 2
Number is: 1Number is: 2Number is: 2
电话号码是:1
电话号码是:2
号码是:1号码是:2
数字是:1数字是:2数字是:2
你把这件事复杂化了很多。您不需要所有这些循环来手动处理事情。您应该利用可用的cmdlet。这将实现您想要的基本功能:
$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
}
谢谢你说得对,我把剧本复杂化了。我倾向于在实验中这样做。您的示例运行得非常好,但如果我希望在作业运行时获取数据,而不是调用wait job,该怎么办?例如,我试图在作业运行时(这是脚本底部所有循环的点)将任何输出(通过写主机)从作业管道传输到主powershell控制台。通过这样做,我是否走上了“这不是工作的目的/功能”的道路?是否所有作业都要等待完成后才能调用
接收作业
?并不是说这不是作业的“目的”,只是这不是它们最擅长的,也不是您拥有cmdlet支持的目的。您可以执行各种疯狂的循环和完成检查,并获得一些“流”行为的外观,但这将非常复杂且容易出错。这是你的成本/收益决定。作业最擅长的是“我会去做这项工作,当我完成后,你可以处理结果。”如果你想要流式处理,你可以让每个作业写入不同的日志文件,然后启动“尾部”流程来流式处理每个日志。谢谢你,你帮了我很大的忙。在处理一些使用作业的示例项目时,我会记住您的建议。