问题描述
我创建了一个Windows窗体,您可以在其中单击一个按钮来启动大约15分钟的备份过程(使用 Start-Job
).我使用 Start-Job
来保持表单在备份过程中的响应速度(通过响应,我是说您可以移动它,将其最小化,等等).但是,我希望表单在工作完成后弹出一个消息框,而我无法设法获得正确的结果.
I've created a Windows form where you can click a button that starts a backup process (Using Start-Job
) of about 15 minutes.I used Start-Job
in order to keep the form responsive during the backup process (By responsive I mean you can move it around, minimize it and so on).However, I would like the form to pop up a message box once the job is completed and I can't manage to get to the right result.
起初,我尝试了一个 While
循环,该循环每10秒检查一次作业是否完成:
At first I tried a While
loop that checks every 10 seconds if the job is completed:
$BackupButton.Add_Click( {
$BackupJob = Start-Job -ScriptBlock { ... }
$Completed = $false
while (!($Completed)) {
if ($BackupJob.State -ne "Running") {
$Completed = $true
}
Start-Sleep -Seconds 10
}
[System.Windows.Forms.MessageBox]::Show('Successfully completed the backup process.', 'Backup Tool', 'OK', 'Info')
})
作业完成后,这给了我一个消息框,但表单在此过程中没有响应,可能是因为它仍在 While
循环中使用线程的资源.
This gave me the message box after the job completed but the form was unresponsive during the process, probably because it was still using the thread's resources for the While
loop.
然后,我尝试使用 Register-ObjectEvent
调用消息框以显示作业状态何时更改:
Then, I tried using Register-ObjectEvent
to call the message box to show when the job's state has changed:
$BackupButton.Add_Click( {
$BackupJob = Start-Job -ScriptBlock { ... }
Register-ObjectEvent $BackupJob StateChanged -Action {
[System.Windows.Forms.MessageBox]::Show('Successfully completed the backup process.', 'Backup Tool', 'OK', 'Info')
}
})
此选项的确使表单在此过程中保持响应,但是直到我关闭Windows表单时,消息框(事件的动作块)才开始启动.
This option did keep the form responsive during the process, but the message box (The event's action block) never started, until the moment I closed the Windows form.
是否有任何选项既可以使消息框按时显示(在窗体关闭时不显示),又可以不使用窗体的线程(保持响应状态)?
Is there any option that will both make the message box appear on time (Not when the form closes) and not use the form's thread (Keep it responsive)?
编辑:或者,是否可以通过后台作业控制我的表单?我试图将表单的按钮/控件作为作业的参数发送,然后从作业中控制表单的事件,但是它不起作用.如果可以通过某种方式从后台作业访问表单,这也可以解决我的问题.
Alternatively, is there a way to control my form from the background job? I tried to send the form's buttons/controls as arguments to the job and then control the form's events from the job but it didn't work.If there's a way to somehow access the form from the background job, this will also solve my problem.
谢谢.
推荐答案
开始睡眠
cmdlet使您的表单无响应.为了克服这个问题,请改用 System.Windows.Forms.Timer
对象.
The Start-Sleep
cmdlet makes your form unresponsive. To overcome that, use a System.Windows.Forms.Timer
object instead.
类似的东西:
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 1000 # for demo 1 second
$timer.Enabled = $false # disabled at first
$timer.Add_Tick({
# check every 'Interval' milliseconds to see if the backup job is still running
# if not, stop the timer (this will set the Enabled property to $false)
if ($script:BackupJob.State -ne "Running") { $timer.Stop() }
})
$BackupButton = New-Object System.Windows.Forms.Button
$BackupButton.Anchor = 'Top','Left'
$BackupButton.Size = [System.Drawing.Size]::new(120, 31)
$BackupButton.Location = [System.Drawing.Point]::new(($form.Width - $BackupButton.Width) / 2, 150)
$BackupButton.Text = 'Start Backup'
$BackupButton.Add_Click( {
Write-Host "Job started"
$this.Enabled = $false # disable the button, to prevent multiple clicks
# use the script: scope, otherwise the timer event will not have access to it
# for demo, the job does nothing but wait..
$script:BackupJob = Start-Job -ScriptBlock { Start-Sleep -Seconds 5 }
$timer.Start()
while ($timer.Enabled) {
[System.Windows.Forms.Application]::DoEvents()
}
Write-Host "Job ended"
# show the messagebox
[System.Windows.Forms.MessageBox]::Show('Successfully completed the backup process.', 'Backup Tool', 'OK', 'Info')
# and enable the button again
$this.Enabled = $true
})
希望有帮助
这篇关于如何在PowerShell中检查后台作业是否完成但保持Windows窗体响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!