如何在PowerShell中检查后台作业是否完成但保持Windows窗体响应 [英] How to check if a background job completed but keep the Windows form responsive in PowerShell

查看:91
本文介绍了如何在PowerShell中检查后台作业是否完成但保持Windows窗体响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个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窗体响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆