Powershell:从后台作业结果更新 GUI

Luk*_*itt 5 forms powershell user-interface jobs timer

编辑:我能够让它工作,请参阅下面的解决方案。下面的评论者是正确的,即 Powershell 并不是 GUI 和线程的理想选择,但它可以做到。


我在 Powershell 中有一个表单,它使用 Start-Job 在后台运行函数而不会冻结 GUI。我的目标是不断检查这些作业的输出状态。我设法使用 Windows Forms Timer 来检查作业的结果并相应地更新 GUI。

一切正常,但似乎很草率。这是完成 GUI 刷新的最佳方式吗?我对 Powershell 比较陌生,我想改进我的编码。

我在做什么的例子:

$jobScript = {
    Start-Sleep 5
    Write-Output "The job has finished running"
}

$timerScript = {
    $timer.Stop()
    $jobResult = Get-Job | Receive-Job -Keep
    if ($jobResult) {
        $btn.text = $jobResult
    } else {
        $timer.Start()
    }
}

Add-Type -AssemblyName System.Windows.Forms
$form             = New-Object System.Windows.Forms.Form
$form.ClientSize  = '300,300'
$form.topmost     = $true

$btn              = New-Object System.Windows.Forms.Button
$btn.Text         = "The job is still running"
$btn.Width        = 300
$btn.Height       = 300
$form.Controls.Add($btn)

$timer            = New-Object System.Windows.Forms.Timer
$timer.Interval   = 100
$timer.add_Tick($timerScript)
$timer.Start()

Start-Job -ScriptBlock $jobScript

$form.ShowDialog()
Run Code Online (Sandbox Code Playgroud)

更新:我的解决方案

使用Register-ObjectEvent不起作用,似乎它正在与线程的 GUI 进行斗争。相反,我能够使用[System.Windows.Forms.Application]::DoEvents(). 这允许 GUI 四处移动,一旦完成移动,线程将恢复。这里的一个重要警告是,只要 GUI 正在移动,执行就会暂停,因此如果您的代码需要在时间限制内对后台作业做出反应,这可能会导致错误。

示例代码块:

$jobScript =
{
    Start-Sleep 5
    Write-Output "The job is completed"
}

Add-Type -AssemblyName System.Windows.Forms
$form             = New-Object System.Windows.Forms.Form
$form.ClientSize  = '300,300'
$form.topmost     = $true

$btn              = New-Object System.Windows.Forms.Button
$btn.Text         = "..."
$btn.Width        = 300
$btn.Height       = 300
$form.Controls.Add($btn)

$btn.add_click({
    $btn.Text = "Starting job"
    $jobby = Start-Job -ScriptBlock $jobScript
    Do {[System.Windows.Forms.Application]::DoEvents()} Until ($jobby.State -eq "Completed")
    $btn.Text = Get-Job | Receive-Job
})

$form.ShowDialog()
Run Code Online (Sandbox Code Playgroud)

Ada*_*dam -1

您可能想将其发布到CodeReview.StackExchange.com上。

我有点讨厌人们在 Powershell 中构建 UI。如果您想要一个合适的 Windows 窗体应用程序,只需用 C# 编写即可。所以我不同意这个设计的前提。

我喜欢你放弃投票设计的冲动;您启动该作业,然后轮询以查看它是否已完成。我认为事件处理程序可能是更好的选择。查看PowerShell 和事件:对象事件一文中的“监视后台作业”部分。这是一个老东西,但一个好东西。