Nig*_*Job 5 powershell jobs multithreading winforms
Start-Job我创建了一个 Windows 表单,您可以在其中单击一个按钮来启动大约 15 分钟的备份过程(使用)。我使用它是Start-Job为了在备份过程中保持表单响应(响应式我的意思是你可以移动它,最小化它等等)。但是,我希望表单在工作完成后弹出一个消息框,但我无法获得正确的结果。
首先,我尝试了一个While循环,每 10 秒检查一次作业是否完成:
$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')
})
Run Code Online (Sandbox Code Playgroud)
这在作业完成后给了我一个消息框,但表单在此过程中没有响应,可能是因为它仍在循环中使用线程的资源While。
然后,我尝试使用Register-ObjectEvent调用消息框来显示作业状态何时更改:
$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')
}
})
Run Code Online (Sandbox Code Playgroud)
此选项确实使表单在此过程中保持响应,但消息框(事件的操作块)从未启动,直到我关闭 Windows 表单的那一刻。
是否有任何选项可以使消息框按时显示(不在表单关闭时)并且不使用表单的线程(保持响应)?
编辑:或者,有没有办法从后台作业控制我的表单?我尝试将表单的按钮/控件作为参数发送给作业,然后从作业控制表单的事件,但它不起作用。如果有办法以某种方式从后台作业访问表单,这也将解决我的问题。
提前致谢。
该Start-Sleepcmdlet 使您的表单无响应。为了克服这个问题,可以使用一个System.Windows.Forms.Timer对象来代替。
就像是:
$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
})
Run Code Online (Sandbox Code Playgroud)
希望有帮助
| 归档时间: |
|
| 查看次数: |
967 次 |
| 最近记录: |