Performance of PowerShell-Scripts when using WinForms and jobs

61 Views Asked by At

Im coding a powershell script which contains multiple forms. Eg. i have a main form with a button. if i klick the button a second form opens. This second form is initialized through a job (start-job). Although this also works without the job, i still prefer this approach since as i understand its considered best practice with winforms. The problem is that the execution time if using a job is significant longer and therefor the application feels unresponsive.

output of measure-command.

  • without job: Job execution time: 4.1125 milliseconds
  • with job: Job execution time: 1348.9928 milliseconds

I would like to find a way to speed up the job execution. Does anyone have a hint, what i can change or is this just work as designed?

Thanks in advance



function New-SecondForm {
    param(
        $text
    )
          
    Add-Type -AssemblyName System.Windows.Forms
    $popOutForm = New-Object System.Windows.Forms.Form
    $popOutForm.Size = New-Object System.Drawing.Size(400, 300)
    $popOutForm.Text = "SecondForm"

    $enlargedTextBox = New-Object System.Windows.Forms.RichTextBox
    $enlargedTextBox.Dock = "Fill"
    $enlargedTextBox.Multiline = $true
    $enlargedTextBox.ReadOnly = $true
 
    $popOutForm.Controls.Add($enlargedTextBox)
        
    #$popOutForm.ShowDialog() 
 
}

function New-SecondFormJob {
    param(
        $text
    )
   
    $scriptBlock = {
        
        Add-Type -AssemblyName System.Windows.Forms
        $popOutForm = New-Object System.Windows.Forms.Form
        $popOutForm.Size = New-Object System.Drawing.Size(400, 300)
        $popOutForm.Text = "SecondForm"

        $enlargedTextBox = New-Object System.Windows.Forms.RichTextBox
        $enlargedTextBox.Dock = "Fill"
        $enlargedTextBox.Multiline = $true
        $enlargedTextBox.ReadOnly = $true
 
        $popOutForm.Controls.Add($enlargedTextBox)
        
        #$popOutForm.ShowDialog() 
    }

    $job = Start-Job -ScriptBlock $scriptBlock 
    Wait-Job $job | Out-Null
    Remove-Job $job
}


Add-Type -AssemblyName System.Windows.Forms

$form = New-Object System.Windows.Forms.Form
$form.Text = "PowerShell WinForms Example"
$form.Size = New-Object System.Drawing.Size(300, 200)
$form.StartPosition = "CenterScreen"

$button = New-Object System.Windows.Forms.Button
$button.Text = "New-SecondForm"
$button.Location = New-Object System.Drawing.Point(100, 50)
$button.Size = New-Object System.Drawing.Size(100, 30)

$button2 = New-Object System.Windows.Forms.Button
$button2.Text = "New-SecondFormJob"
$button2.Location = New-Object System.Drawing.Point(100, 100)
$button2.Size = New-Object System.Drawing.Size(100, 30)

$button.Add_Click({
        $executionTime = Measure-Command { New-SecondForm } | Select-Object -ExpandProperty TotalMilliseconds
        Write-Host = "Job execution time: $executionTime milliseconds"
    })


$button2.Add_Click({
        $executionTime = Measure-Command { New-SecondFormJob } | Select-Object -ExpandProperty TotalMilliseconds
        Write-Host = "Job execution time: $executionTime milliseconds"
    })



$form.Controls.Add($button)
$form.Controls.Add($button2)
$form.ShowDialog()


1

There are 1 best solutions below

0
McLovin On

instead of:

$job = Start-Job -ScriptBlock $scriptBlock
Wait-Job $job | Out-Null
Remove-Job $job

ive used:

$newPowerShell = [PowerShell]::Create().AddScript($scriptBlock)
$job = $newPowerShell.BeginInvoke()
While (-Not $job.IsCompleted) {}
$newPowerShell.EndInvoke($job)
$newPowerShell.Dispose()

which resulted in:

  • without job: Job execution time: 4.1125 milliseconds
  • with job: Job execution time: 1348.9928 milliseconds
  • with runspace: Job execution time: 25.1892 milliseconds