PowerShell: ação de evento de tarefa com formulário não executado
Se eu executar o seguinte código, a Ação do Evento será executada:
$Job = Start-Job {'abc'}
Register-ObjectEvent -InputObject $Job -EventName StateChanged `
-Action {
Start-Sleep -Seconds 1
Write-Host '*Event-Action*'
}
A corda ' Ação do Evento' é exibido
Se eu usar um formulário e iniciar o código acima, clicando em um botão,
A ação do evento não é executada:
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$Form1 = New-Object Windows.Forms.Form
$Form1.Add_Shown({
$Form1.Activate()
})
$Button1 = New-Object System.Windows.Forms.Button
$Button1.Text = 'Test'
$Form1.Controls.Add($Button1)
$Button1.Add_Click({
Write-Host 'Test-Button was clicked'
$Job = Start-Job {'abc'}
Register-ObjectEvent -InputObject $Job -EventName StateChanged `
-Action {
Start-Sleep -Seconds 1
Write-Host '*Event-Action*'
}
})
$Form1.ShowDialog()
Só quando clico no botão novamente, a primeira Ação de Evento é executad
Com o terceiro clique, a segunda Ação de Evento é executada e assim por diant
Se eu fizer vários cliques em rápida sucessão, o resultado é imprevisíve
lém disso, quando fecho o formulário com o botão no canto superior direito,
A última ação de evento "aberta" é executad
ota: Para testar o PowerShell ISE, é preferível, porque o PS Console exibe
a corda somente sob certas circunstância
lguém pode me dar uma pista do que está acontecendo aqu
Desde já, obrigado
nimizen.
Obrigado pela sua explicação, mas eu realmente não entendo por que o evento StateChanged não é acionado ou visível para o script principal até que haja alguma ação com o formulário. Eu apreciaria outra tentativa de me explica
O que eu quero realizar é uma espécie de multithreading com PowerShell e Form
Meu plano é o seguinte:
'
O script mostra um formulário para o usuári
O usuário faz alguma entrada e clica em um botão. Com base na entrada do usuário, um conjunto de trabalhos é iniciado com Start-Job e um evento StateChanged é registrado para cada trabalh
Enquanto os trabalhos estão em execução, o usuário pode executar qualquer ação no formulário (incluindo interromper os trabalhos por meio de um botão) e o formulário é repintado quando necessári
O script reage a qualquer evento disparado pelo Formulário ou por seus controles filh
Também o script reage ao evento StateChanged de cada trabalh
Quando ocorre um evento StateChanged, o estado de cada trabalho é inspecionado e, se todos os trabalhos tiverem o estado 'Concluído', os resultados dos trabalhos serão buscados com Receive-Job e exibidos ao usuári
'
Tudo isso funciona bem, exceto que o evento StateChanged não é visível para o script principa
A descrição acima ainda é minha solução favorita e, se você tem alguma idéia de como implementar isso, entre em contat
Caso contrário, provavelmente vou recorrer a uma solução alternativa, que pelo menos dê ao usuário uma sensação de multithreading. É ilustrado no seguinte exemplo:
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$Form1 = New-Object Windows.Forms.Form
$Form1.Add_Shown({
$Form1.Activate()
})
$Button1 = New-Object System.Windows.Forms.Button
$Button1.Text = 'Test'
$Form1.Controls.Add($Button1)
$Button1.Add_Click({
$Form1.Focus()
Write-Host 'Test-Button was clicked'
$Job = Start-Job {Start-Sleep -Seconds 1; 'abc'}
Do {
Start-Sleep -Milliseconds 100
Write-Host 'JobState: ' $Job.State
[System.Windows.Forms.Application]::DoEvents()
}
Until ($Job.State -eq 'Completed')
Write-Host '*Action*'
})
$Form1.ShowDialog()