Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Forms Powershell:从后台作业结果更新GUI_Forms_Powershell_User Interface_Timer_Jobs - Fatal编程技术网

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

Forms Powershell:从后台作业结果更新GUI,forms,powershell,user-interface,timer,jobs,Forms,Powershell,User Interface,Timer,Jobs,编辑:我能够让它工作,请参阅下面的解决方案。下面的评论是正确的,Powershell并不是GUI和线程的理想选择,但它是可以做到的 我在Powershell中有一个表单,它使用Start Job在后台运行函数,而不冻结GUI。我的目标是不断检查这些工作的产出状态。我设法使用Windows窗体计时器来检查作业的结果,并相应地更新GUI 这一切都很好,但它似乎马虎。这是完成GUI刷新的最佳方法吗?我对Powershell比较陌生,我想改进我的编码 我正在做的示例: $jobScript = {

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


我在Powershell中有一个表单,它使用Start Job在后台运行函数,而不冻结GUI。我的目标是不断检查这些工作的产出状态。我设法使用Windows窗体计时器来检查作业的结果,并相应地更新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()

更新:我的解决方案

使用
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()

你可能想把这篇文章发到网上

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

我喜欢你离开投票站设计的冲动;您启动作业,然后轮询以查看作业是否已完成。我认为事件处理程序可能是更好的选择。查看文章中的“监视后台作业”部分。这是一个古老而美好的故事。

您可以使用事件:

 $job = Start-Job {sleep 3; Write-Output "Dummy job completed"}

$callback = {

Write-Host "Event Fired"
Unregister-Event -SourceIdentifier "DummyJob"
Write-Host ($job | Receive-Job)

}

$evt = Register-ObjectEvent -InputObject $job -EventName StateChanged -SourceIdentifier "DummyJob" -Action $callback 


# to remove all 
Get-Job | Remove-Job -Force # jobs and events
Get-EventSubscriber | Unregister-Event  # events

PowerShell显示进度的方式是使用
写入进度
。请参阅
Get Help Write Progress-examples
@KoryGill With winform applications它不是。@KoryGill感谢您的回复。我真正的问题是,如何让表单在后台作业返回结果后等待并更新,无论是使用
写入进度
还是使用
写入输出
在Powershell中制作响应性winforms GUI都是一件非常痛苦的事。我会考虑和其他用户互动的方式。非常感谢你的回复和链接。请你扩展一下为什么你不喜欢PuxBug GUI?我想这只是一种变通方法,而不是预期用途?这是一个很好的问题。我可以用我的自行车发电。这种方法可以让我保持健康,而且更环保。Powershell的UI有点像这样。我能做到。它使UI开发更容易访问,特别是对于Powershell开发人员。然而,Powershell并不是为了达到这个目的,在GUI竞技场上也没有太多的游戏时间。出于这个原因,你会发现你在兔子洞里钻得越深,你就会发现小陷阱。如果你坚持使用为UI开发设计的语言,你会遇到更少的麻烦。对不起,我不得不简短地说;字符限制。很好的类比,再次感谢您的时间。我最终找到了一个更好的解决方案(我会编辑我的OP),但我肯定会开始用其他语言为未来做准备。你可以用C#做你能做的一切。您可以在PoSh中构建非常好的UI(示例:)。与使用c#相比,它不那么复杂,工作量也更少。谢谢!在我开始使用C#之前,我会一直把它作为一种解决方法来研究,我一直听说我应该这样做。使用它进行一些测试,
Register ObjectEvent
在使用winforms时会产生奇怪的结果。我在谷歌上搜索了一下,它似乎在与表单争夺线程。我将用最终找到的解决方案更新OP。