为所有后台作业注册跟踪事件?

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
}

起初我什至不知道这是可能的,所以感谢您指出这一点。好问题:)