Background Tasks on WebMap

There are several ways to start tasks on the background thread in .NET.

In this post I will cover the BackgroundWorker alternative.

The BackgroundWorker component was introduced in .NET2 and is designed to make it really easy for developers to run a task on a background task. It covers all the basics of reporting progress cancellation, catching exceptions.

To use it you put the code for your background thread into the DoWork event handler of the background worker:

backgroundWorker1.DoWork += BackgroundWorker1OnDoWork;

and within that function you are able to report progress:

backgroundWorker1.ReportProgress(50, progressMessage);

To cancel, you can call the backgroundWorker1.CancelAsync()
this will turn the backgroundWorker1.CancellationPending flag, which you can use inside your code to stop work.

The BackgroundWorker provides a RunWorkerCompleted event that you subscribe to get hold of the results of the background task.

So let's see an example:

This application will just trigger a background tasks that will increase a counter. And it can be cancelled by pressing stop.

The background worker can be use pretty much the same on way on WebMap app. However there are a couple of considerations:

  • Code executed on the background thread cannot create observable objects or properties.
  • You can use properties on an observable object as long as they are not intercepted.
  • You need to use a Mobilize.Web.Timer in order to get the UI updated.

Ok. So for example in order to start your background thread use a code as the following:

       private void BtnStart_Click(object sender, EventArgs e)
       {
            this.timer.Enabled = true;
            this.lblCounterValue.Text = "0";
            this.backgroundWorker.RunWorkerAsync();
       }

Stoping is also simple:

        private void BtnStop_Click(object sender, EventArgs e)
       {
            this.timer.Enabled = false;
            this.backgroundWorker.CancelAsync();
        }

The background processing will happen on the DoWork method:

       private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
       {
            //WARNING: No observable objects can be used on the 
            //background thread
            int total = 1000;
            
            for (int counter = 1; counter < total; counter++)
            {
                if (backgroundWorker.CancellationPending)
                {
                    backgroundWorker.ReportProgress(0, "Cancelled");
                    break;
                }
                backgroundWorker.ReportProgress(counter, "Working...");
                System.Threading.Thread.Sleep(1000);

            }
            
        }

Progress report should be stored on non-intercepted properties:

private string LastProcessMessage;
private int LastProgressPercentage;
private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
   this.LastProcessMessage = e.UserState.ToString();
  this.LastProgressPercentage = e.ProgressPercentage;
}

To get the changes on the UI. Just let the timer handle that:

private void Timer_Tick(object sender, EventArgs e)
{
     this.lblCounterValue.Text = this.LastProgressPercentage.ToString();
}

Just remember that you need to update you form by adding a timer to your html:

<wm-timer [model]="model.timer"></wm-timer>

And that is pretty much it. :)