为所有后台作业注册跟踪事件?
Register trackingevent for all background jobs?
下午好,
我一直在尝试根据 所有 作业何时完成来注册事件。我能够成功注册一个,但我想在所有后台作业完成后弹出一条消息。有人熟悉如何操作吗?
我尝试了以下操作,但错误提示作业为空:
1..10 | ForEach-Object -Process {
Start-Job { Start-Sleep $_ } -Name "$_" | Out-Null} -OutVariable $jobs
Register-ObjectEvent $jobs StateChanged -Action {
[System.Windows.MessageBox]::Show('Done')
$eventSubscriber | Unregister-Event
$eventSubscriber.Action | Remove-Job
} | Out-Null
我觉得 Do{}Until()
循环可以做到,但是我不确定如何注册它以检查直到作业完成。也尝试按照其他人使用不同语言完成的一些方法,但是,我无法接受。
我不想 post 我尝试过的所有内容,所以 post 不会让任何人感到厌烦。也在 google 上进行了搜索,但是,我找不到太多有关为多个作业注册对象的信息。
编辑
这是有效的方法:
$job = Start-Job -Name GetLogFiles { Start-Sleep 10 }
Register-ObjectEvent $job StateChanged -Action {
[System.Windows.MessageBox]::Show('Done')
$eventSubscriber | Unregister-Event
$eventSubscriber.Action | Remove-Job
} | Out-Null
这是我想发生的事情,但要评估所有工作,而不仅仅是一个。
这是个人在监控 运行 作业时使用的:
$jobs= 1..10 | ForEach-Object -Process {
Start-Job { Start-Sleep $using:_ ; "job {0} done" -f $using:_ } -Name "$_"
}
do{
$i = (Get-Job -State Completed).count
$progress = @{
Activity = 'Jobs completed'
Status = "$i of {0}" -f $jobs.Count
PercentComplete = $i / $jobs.count * 100
}
Write-Progress @progress
Start-Sleep -Milliseconds 10
}
until($i -eq $jobs.Count)
$result = Get-Job | Receive-Job
$jobs | Remove-Job
当然,在我知道某些作业可能会失败的某些情况下,我将 until(...)
条件更改为不同的内容,do {...}
包含重新启动失败作业的逻辑。
编辑 1:
值得一提的是,如果您对多线程感兴趣,Start-Job
不值得您花时间,它已被证明在许多情况下比线性循环慢。你应该看看 ThreadJob Module
编辑 2:
经过一些测试,这对我有用:
# Clear the Event queue
Get-EventSubscriber|Unregister-Event
# Clear the Job queue
Get-Job|Remove-Job
1..10 | ForEach-Object -Process {
$job = Start-Job { Sleep -Seconds (1..20|Get-Random) } -Name "$_"
Register-ObjectEvent -InputObject $job -EventName StateChanged -Action {
$eventSubscriber | Unregister-Event
$eventSubscriber.Action | Remove-Job
if(-not (Get-EventSubscriber))
{
[System.Windows.MessageBox]::Show('Done')
}
} | Out-Null
}
起初我什至不知道这是可能的,所以感谢您指出这一点。好问题:)
下午好,
我一直在尝试根据 所有 作业何时完成来注册事件。我能够成功注册一个,但我想在所有后台作业完成后弹出一条消息。有人熟悉如何操作吗?
我尝试了以下操作,但错误提示作业为空:
1..10 | ForEach-Object -Process {
Start-Job { Start-Sleep $_ } -Name "$_" | Out-Null} -OutVariable $jobs
Register-ObjectEvent $jobs StateChanged -Action {
[System.Windows.MessageBox]::Show('Done')
$eventSubscriber | Unregister-Event
$eventSubscriber.Action | Remove-Job
} | Out-Null
我觉得 Do{}Until()
循环可以做到,但是我不确定如何注册它以检查直到作业完成。也尝试按照其他人使用不同语言完成的一些方法,但是,我无法接受。
我不想 post 我尝试过的所有内容,所以 post 不会让任何人感到厌烦。也在 google 上进行了搜索,但是,我找不到太多有关为多个作业注册对象的信息。
编辑 这是有效的方法:
$job = Start-Job -Name GetLogFiles { Start-Sleep 10 }
Register-ObjectEvent $job StateChanged -Action {
[System.Windows.MessageBox]::Show('Done')
$eventSubscriber | Unregister-Event
$eventSubscriber.Action | Remove-Job
} | Out-Null
这是我想发生的事情,但要评估所有工作,而不仅仅是一个。
这是个人在监控 运行 作业时使用的:
$jobs= 1..10 | ForEach-Object -Process {
Start-Job { Start-Sleep $using:_ ; "job {0} done" -f $using:_ } -Name "$_"
}
do{
$i = (Get-Job -State Completed).count
$progress = @{
Activity = 'Jobs completed'
Status = "$i of {0}" -f $jobs.Count
PercentComplete = $i / $jobs.count * 100
}
Write-Progress @progress
Start-Sleep -Milliseconds 10
}
until($i -eq $jobs.Count)
$result = Get-Job | Receive-Job
$jobs | Remove-Job
当然,在我知道某些作业可能会失败的某些情况下,我将 until(...)
条件更改为不同的内容,do {...}
包含重新启动失败作业的逻辑。
编辑 1:
值得一提的是,如果您对多线程感兴趣,Start-Job
不值得您花时间,它已被证明在许多情况下比线性循环慢。你应该看看 ThreadJob Module
编辑 2:
经过一些测试,这对我有用:
# Clear the Event queue
Get-EventSubscriber|Unregister-Event
# Clear the Job queue
Get-Job|Remove-Job
1..10 | ForEach-Object -Process {
$job = Start-Job { Sleep -Seconds (1..20|Get-Random) } -Name "$_"
Register-ObjectEvent -InputObject $job -EventName StateChanged -Action {
$eventSubscriber | Unregister-Event
$eventSubscriber.Action | Remove-Job
if(-not (Get-EventSubscriber))
{
[System.Windows.MessageBox]::Show('Done')
}
} | Out-Null
}
起初我什至不知道这是可能的,所以感谢您指出这一点。好问题:)