Progress Bar Series (Part 4) – Handling Steps Progress with a Background Job in a GUI Application

In Part 4 of the Progress Bar series, we integrate a progress bar control in a GUI application that submits a job for background processing. We also demonstrate how to interrupt the running job.

GUI Application for Listing PDF Documents

In this scenario, we show the use of the progress bar while processing a background job. This application is an example of a “responsive” form which prevents the form from freezing during job execution. The form also provides an option to interrupt the job at any time and includes a time-lapse display.

“Start Job” Button Control

In the “Start Job” button control script block, we add the code to initialize the progress bar properties after a folder is selected.

After selecting a folder containing PDF files, we get the total number of files and use that in the Progress Bar Maximum property. Then we initialized both Step and Value properties to 1.

#Initialize the Progress Bar
$progressbar1.Maximum = $files.Count;
$progressbar1.Step = 1;
$progressbar1.Value = 1;

In the “Start Job” button script block, we use our Add-JobTracker Helper function. The following parameters are defined in this function to handle the background job process:

  • Name – The Job-Name for the running job.
  • ArgumentList – (Optional) A single value or an array of values to pass as an Argument to the job.
  • JobScript  – The script code that will be sent to run the background job.
  • UpdateScript – The script code used to update what is going on with the background job.
  • CompletedScript – The script code that will execute when the background job completes processing.

A splatting variable is created holding the parameter’s value to be passed to the Add-JobTracker function:

#Initialize the Progress Bar
$progressbar1.Maximum = $files.Count;
$progressbar1.Step = 1;
$progressbar1.Value = 1;

## - Prepare Splatter variable to submit to background job:
$jobsplat = @{
	Name		    = 'MyJobName'
	ArgumentList    = $selectedPath
	JobScript	    = $jobScript
	UpdateScript    = $updateScript
	CompletedScript = $completedScript
}

At this point, the function will submit the job for processing in the background.

During Job Processing

While the job is processing in the background, the PDF files in the selected folder are being displayed in the output “RichTextBox” control, the timer is counting, and the progress bar increments while processing.

All of this action is being handled by the “UpdateScript” script block section in the Add-JobTracker function:

$updateScript = {
	Param ($Job)
	
	if ($Job.Name -eq 'GetFiles')
	{
		
		## - Grab results from background job:
		$results = Receive-Job -Job $Job
		$richtextbox1.Lines += $results | select -ExpandProperty Fullname
		
		## - Make the text scroll-up while processing:
		$richtextbox1.SelectionStart = $richtextbox1.Text.Length
		$richtextbox1.ScrollToCaret()
		
		## - Increment progress bar:
		$progressbar1.PerformStep();
		
	}
	
	#Animate the Button
	if ($null -ne $buttonStartJob.ImageList)
	{
		if ($buttonStartJob.ImageIndex -lt $buttonStartJob.ImageList.Images.Count - 1)
		{
			$buttonStartJob.ImageIndex += 1
			
			## - Code to Display Time Elapsed:
			$CurrentTime = $Script:Time.Elapsed;
			$DisplayTime = $([string]::Format("Time: {0:d2}:{1:d2}:{2:d2}",
					$CurrentTime.hours,
					$CurrentTime.minutes,
					$CurrentTime.seconds));
			$labelTime.Text = $DisplayTime;
			
		}
		else
		{
			$buttonStartJob.ImageIndex = 0
		}
	}
}

In this section, the progress bar method PerformStep() will trigger the bar to increment.

When the background job ends, the “CompletedScript” script block section executes.  At this point, the total number of PDF files found will display in the “RichTextBox” output area, the total duration of the process will be displayed, and the progress bar will increment to completion.

$completedScript = {
	Param($Job)
	
	if ($Job.Name -eq 'GetPDFFiles')
	{
		## - Get Background Job results:
		$results = Receive-Job -Job $Job;
		$richtextbox1.Lines += $results | select -ExpandProperty Fullname;
		
		## - Display Process Stopped text:
		$richtextbox1.AppendText(("`r`n`r`n*** Process Completed ***`r`n"));
		
		## - Display processing time:
		$richtextbox1.AppendText("`r`n" + "Total Processing $($labelTime.Text)" + "`r`n");
		
		## - Scroll top end of lines:
		$richtextbox1.SelectionStart = $richtextbox1.Text.Length + 4;
		$richtextbox1.ScrollToCaret();
		
		## - Progress Bar fill to end:
		$progressbar1.Increment($richtextbox1.Text.Length);
		$progressbar1.PerformStep();

   }
    
	#Enable the Button
	$buttonStartJob.ImageIndex = -1
	$buttonStartJob.Enabled = $true
	
}

In this section, we use the progress bar method PerformStep() to help complete the bar.

Interrupt the Job

This application includes the ability to stop the job with the “Stop Job” button control. When the job is stopped, the progress bar will stay idle without any increments.

In the “Stop Job” control, both progress bar Value and Step properties are set to 0:

$buttonStopJob_Click = {
	
	Stop-JobTracker
        $this.Enabled = $false
	$buttonStartJob.Enabled = $false
	
	## - Progress bar stop and reset values to 0:
	$progressbar1.Value = 0;
	$progressbar1.Step = 0;
	
	## - Process Abort text:
	$richtextbox1.AppendText(("`r`n`r`n*** Process Stopped ***`r`n"));
}

As you can see, it was simple to integrate the progress bar properties in the Add-Tracker function script block with the button controls.

Summary

We have shown how to integrate the progress bar in a “responsive” application that is handling a background job, with the ability to interrupt the job.

Below is a general view of the logic used in this GUI application sample:

Download Progress Bar sample form: ProgressBarJobTracker_wStopOption1.zip

What’s next?

Next in the series is “Part 5 – Display Progress in a Script (non-GUI) solution”, where will be using the “Write-Progress” cmdlet.

Progress Bar series topics:

Related Articles

Feedback

As always, if you have any ideas, comments, or feedback, please visit our feedback forum and reference this post.

Max Trinidad is a Technology Evangelist at SAPIEN Technologies Inc., and a Microsoft PowerShell MVP. You can reach him at maxt@sapien.com