EDIT: The sample code is far off from the original goal, but there's a legitimate answer to the question that I actually posed, so I've edited the question and title.
I am writing a multithread PowerShell script with a WinForms GUI and would like to update the GUI from one of the other threads in the script. I'm having no luck doing this at all. In fact, I can't even get BeginInvoke
to work.
Here's a very stripped down example. This is sample code, not production, so it's not pretty, but it's replicating the issue:
$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()
I don't even hear the console beep, so it's as if the BeginInvoke
code isn't being executed at all.
If I throw in a [System.Windows.Forms.Application]::DoEvents()
after the Read-Host
then I see the change so it seems to be a timing issue, but I don't want to go into a spin loop or something silly like that - I want to fire and forget the BeginInvoke
and have the results visible as appropriate. I see other answers like the one to PowerShell: Job Event Action with Form not executed but that needs to be in a check, sleep, check loop.
There's got to be a simpler way that I'm missing... what is it?
What is the right solution here?
EDIT: Keith's comment made me realize I missed a key point going from production to the stripped sample code - launching a job is indeed multi-process, but the sample code isn't, so the sample doesn't reflect real life, and I'll have to rethink the whole thing. That all said - the sample code doesn't use jobs, and it doesn't work as I expect either, so I'd like to understand why, even if that doesn't help me in this specific case.