PoshCode Logo PowerShell Code Repository

Boots & Background Jobs by Joel Bennett 4 years ago (modification of post by foureight84 view diff)
diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/2315"></script>download | new post

This sample was put together with Jaykul’s help and bits and pieces were taken from the Sample.ps1 distributed with PowerBoots. It requires the current changeset of PowerBoots. Not the 0.2 beta.

Shows how you can invoke a long running function from an event handler using background jobs in order to maintain UI responsiveness.

  1. ## NOTE: This requires the current changeset download of PowerBoots (not the 0.2 beta)
  2. Import-Module PowerBoots
  3.  
  4. # This simulates a download function, say Jaykul's Get-Webfile
  5. # You can output current progress for a large file, or if it's an array of links then out put the current (index/length)%
  6. # You will need to run the function as a background thread in order for it to not interfere with the UI thread (freezes UI) when called from event handler.
  7. Function global:Start-FakeDownload {
  8.         $global:job = Start-Job {
  9.       $max = 50
  10.                 foreach ($i in $(1..$max)){
  11.                         sleep 1 # lock up the thread for a second at a time
  12.                         ($i/$max) * 100 # return a number we can use for progress reporting
  13.                 }
  14.         }
  15. }
  16.  
  17. # GUI using boots. Registers controls as global variables.
  18. $global:Window = Boots -Width 250 -Async -Passthru -Title "Progress Meter" {
  19.         DockPanel  {
  20.                 ProgressBar -Height 25 -Name "Progress" -Dock Top | tee -var global:progress
  21.                 Statusbar { Textblock | Tee -var global:status } -Dock Bottom
  22.                 WrapPanel { Button "Download" -Name "Download" | tee -var global:download } -horizontalalignment center
  23.         } -LastChildFill
  24. }
  25.  
  26. # Add event handler for the Download button.
  27. # Runs Background job and updates Ui
  28. $download.Add_Click({
  29.         # Prevents download from being pressed while running ... causes overload with $timer.
  30.         $download.IsEnabled = $false
  31.         $download.Content = "Downloading..."
  32.         # Get background job out and updates controls with value
  33.         $updateblock = {
  34.                 # Notice the -Keep usage. Job result/output clears everytime you Receive-Job.
  35.                 # -Keep allows us to get the result from the background job multiple times and also serves as a marker to figure out when the job completes
  36.                 if($($job.State -eq "Running") -or $($($job.State -eq "Completed") -and $($(Receive-Job $job -Keep)[-1] -eq 100))){
  37.                         Invoke-BootsWindow $Window {
  38.                                 $progress.Value = $(Receive-Job $job -Keep)[-1]
  39.                                 $status.Text = "$($(Receive-Job $job)[-1])`% done"
  40.                         }
  41.                 }
  42.                 if($($job.State -eq "Completed") -and $($(Receive-Job $job) -eq $null)){
  43.                         Invoke-BootsWindow $Window {
  44.                                 $status.Text = "Download Complete"
  45.                         }
  46.                         $timer.Stop()
  47.                         $download.Content = "Download"
  48.                         $download.IsEnabled = $true
  49.                 }
  50.         }
  51.         $timer = new-object System.Windows.Threading.DispatcherTimer
  52.         $timer.Interval = [TimeSpan]"0:0:3"
  53.         $timer.Add_Tick( $updateBlock )
  54.         Start-FakeDownload
  55.         $timer.start()
  56. })

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me