The BackgroundWorker or "How to make responsive WPF windows"

Public forum to share code snippets, screen shorts, experiences, etc.
Post Reply
User avatar
wriedmann
Posts: 3644
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

The BackgroundWorker or "How to make responsive WPF windows"

Post by wriedmann »

Unfortunately, in WPF the AppExec() call does not work if you start a longer process from your window.
The first approach would be to use ASYNC/AWAIT, but unfortunately this works only if you are using some methods that are implementing this.

For own processings, the BackgroundWorker class (from System.ComponentModel) seems to be a better solution.

Please look at this code (how to start such a processing):

Code: Select all

method StartButtonClick( oSender as object, e as RoutedEventArgs ) as void   
	
if _oWorker == null
  _oWorker := BackgroundWorker{}
  _oWorker:WorkerReportsProgress := true
  _oWorker:WorkerSupportsCancellation := true
  _oWorker:DoWork += ExecuteProcessAsync
  _oWorker:ProgressChanged += ProgressProcessAsync
  _oWorker:RunWorkerCompleted += CompletedProcessAsync
  _oWorker:RunWorkerAsync() 
endif
	
return

method ExecuteProcessAsync( oSender as object, e as DoWorkEventArgs ) as void
  local oProcess as AsyncProcess
	
  oProcess := AsyncProcess{ _oWorker }
  oProcess:Process()
	
return
and the relative AsyncProcess implementation:

Code: Select all

class AsyncProcess
  protect _oWorker as BackgroundWorker
	
constructor( oWorker as BackgroundWorker )
	
  _oWorker := oWorker
	
  return	
	
method Process() as void 
  local nLoop as int
  local nInner as int
  local nMax as int
  local cString as string
  local cMessage as string
	
  nMax := 32000
  for nLoop := 1 upto nMax
    for nInner := 1 upto nMax
      cString := string{ 'X', nMax }
    next              
    cMessage := String.Format( "round {0} of {1}", nLoop:ToString(), nMax:ToString() ) 
    _oWorker:ReportProgress( ( nLoop * 100 / nMax ), cMessage )
    Thread.Sleep( 100 )      
    if _oWorker:CancellationPending
       exit
    endif
   next   
   _oWorker:ReportProgress( ( nLoop * 100 / nMax ), "terminated" )
	
end class
You can find the complete working program as attachment to this message - it is a zipped XIDE export file.

Wolfgang
Attachments
BackgroundworkerApp.zip
(3.1 KiB) Downloaded 27 times
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
NickFriend
Posts: 248
Joined: Fri Oct 14, 2016 7:09 am

The BackgroundWorker or "How to make responsive WPF windows"

Post by NickFriend »

Hi Wolfgang,

Task/await, etc. is well worth getting into, as it simplifies the coding of asynchronous code dramatically.

As a starting point you can run more or less any method asynchronously like this (sorry about the C#)...

Code: Select all

private async void MethodA()
{
    await Task.Factory.StartNew(()=> { this.MethodB(); }); 
    // MethodB called asynchronously, control returns immediately to whatever called MethodA
    ... code here gets executed when MethodB completes...
}
Creating your own asynchronous methods is actually quite straightforward as well, once you work out how to do it (as ever that's the difficult bit). But it does make async code much more readable and manageable.

Nick
User avatar
wriedmann
Posts: 3644
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

The BackgroundWorker or "How to make responsive WPF windows"

Post by wriedmann »

Hi Nick,

before discovering the BackgroundWorker class I had tried (successfully) ASYNC/AWAIT, but I feel the BackgroundWorker is a bit clearer to use, and it needs less and clearer code for implementing progress information and the possibility to abort the background process.

Therefore I think the BackgroundWorker is better suited for my needs.

Wolfgang

P.S. I have to admit that it took some time to understand ASYNC/AWAIT. I have added my async/await sample here as attachment.
Attachments
AsyncApp.zip
(3.66 KiB) Downloaded 31 times
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
NickFriend
Posts: 248
Joined: Fri Oct 14, 2016 7:09 am

The BackgroundWorker or "How to make responsive WPF windows"

Post by NickFriend »

Hi Wolfgang,

I like your Task/await version better! But of course everyone has their own preferred style.

Nick
User avatar
wriedmann
Posts: 3644
Joined: Mon Nov 02, 2015 5:07 pm
Location: Italy

The BackgroundWorker or "How to make responsive WPF windows"

Post by wriedmann »

Hi Nick,

did you know that one: ask 5 programmers for a solution of a programming problem, and you'll receive at least 10 different solutions.

Styles and preferences are different - and I'm pretty sure my preferences are a bit unusual for the .NET world, as I prefer code to XAML.

Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
User avatar
Phil Hepburn
Posts: 743
Joined: Sun Sep 11, 2016 2:16 pm

The BackgroundWorker or "How to make responsive WPF windows"

Post by Phil Hepburn »

Be CAREFUL Wolfgang - its party season, and you may not get many invitations ;-0)

Have a season drink on me - Ho ! Ho! Ho!

Guess who ?

:-0))
Post Reply