РЕДАКТИРОВАТЬ: Я смог заставить его работать, см. Мое решение ниже.Приведенные ниже комментарии верны, что Powershell на самом деле не идеален для графического интерфейса и многопоточности, но это можно сделать.
У меня есть форма в Powershell, которая использует Start-Job для запуска функций вфон без зависания графического интерфейса.Моя цель - постоянно проверять состояние этих заданий на предмет их вывода.Мне удалось использовать таймер Windows Forms, чтобы проверить результаты работы и соответствующим образом обновить графический интерфейс.
Все работает нормально, но кажется неаккуратным.Это лучший способ обновления графического интерфейса?Я относительно новичок в 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
не сработало, казалось, что оно борется с графическим интерфейсом для потока.Вместо этого я смог использовать [System.Windows.Forms.Application]::DoEvents()
.Это позволяет перемещать графический интерфейс, и как только он будет перемещен, поток возобновится.Большое предостережение заключается в том, что выполнение приостанавливается до тех пор, пока перемещается графический интерфейс, поэтому, если ваш код должен реагировать на фоновое задание в течение определенного времени, это может вызвать ошибки.
Пример блока кода:
$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()