编辑:示例代码与最初的目标相去甚远,但我实际提出的问题有一个合理的答案,所以我编辑了问题和标题。
我正在使用 WinForms GUI 编写多线程 PowerShell 脚本,并希望从脚本中的其他线程之一更新 GUI。我做这件事一点运气都没有。事实上,我什至不能BeginInvoke
去上班。
这是一个非常精简的示例。这是示例代码,而不是生产,所以它不是很漂亮,但它正在复制问题:
$script:SynchronizedUIHash = [Hashtable]::Synchronized(@{});
[reflection.assembly]::LoadWithPartialName( "System.Windows.Forms")
$form= New-Object Windows.Forms.Form
$label = New-Object Windows.Forms.Label
$label.Text = 'original'
$script:SynchronizedUIHash.label = $label
$form.Controls.add($label)
$form.show()
[System.Windows.Forms.Application]::DoEvents()
Read-Host
$label.BeginInvoke(
[Action[string]] {
param($Message)
[Console]::Beep(500,300)
$l = $SynchronizedUIHash.label
$l.Text = $Message
[System.Windows.Forms.Application]::DoEvents()
},
'changed'
)
Read-Host
$form.close()
我什至没有听到控制台哔哔声,所以好像BeginInvoke
代码根本没有被执行。
[System.Windows.Forms.Application]::DoEvents()
如果我在之后投入 a ,Read-Host
那么我会看到变化,所以这似乎是一个时间问题,但我不想进入自旋循环或类似的愚蠢 - 我想开火并忘记BeginInvoke
并得到结果视情况可见。我看到了其他答案,例如PowerShell: Job Event Action with Form not executed but that need to be in a check, sleep, check loop。
必须有一种更简单的方法,我错过了......它是什么?
什么是正确的解决方案?
编辑:基思的评论让我意识到我错过了从生产到剥离示例代码的关键点——启动工作确实是多进程的,但示例代码不是,所以示例不能反映现实生活,我将不得不重新考虑整个事情。话虽如此 - 示例代码不使用作业,它也不能按我的预期工作,所以我想了解原因,即使在这种特定情况下这对我没有帮助。