How to create a time based & cancelable BackgroundWorker for Windows Phone (and others)

backgroundworkerTimebased

While working on my current project, I needed a solution for a running code with a time offset. Well, you might say, no problem after all, and it is true.

The challenge at this point was to find a way to keep it cancelable at any time. And so the fun started.

After digging a bit deeper into the MSDN documentation, the BackgroundWorker class already have a bunch of methods and properties that are very helpful for this case.

As it is always the case when you work with multiple threads, it can cause some headache. But I got around it and thought it might be helpful for some of you.

Here is how I solved the scenario:

First, declare a static BackgroundWorker so you need to set it up only once on the page you want to use it. In the Loaded or OnNavigatedTo event, we are instantiating our BackgroundWorker.

worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true;
worker.WorkerReportsProgress = true;

Now, let’s add two very important properties: WorkerSupportsCancellation and WorkerReportsProgress. Both need to be set to true, otherwise you will get one InvalidOperationException after the other when running the code.

In my case, I created a separate method to start the BackgroundWorker and hook up to all important events:

        private void RunBackgroundWorker()
        {
            worker.RunWorkerCompleted += worker_RunBackgroundWorkerCompleted;

            //delegating the DoWork event
            worker.DoWork += ((s, args) =>
            {
                //generating a loop
                for (int i = 0; i < 100; i++)
                {

                    if (worker.CancellationPending == true)
                    {
                        //set cancel to true to finish the cancellation on the next run in the loop
                        args.Cancel = true;
                    }
                    else
                    {
                        //calculate your time: seconds * 1000 / 100
                        Thread.Sleep(50);
                        worker.ReportProgress(i);
                    }
                }
            });

            //can be used to fill a progress bar/show percentage
            worker.ProgressChanged += worker_ProgressChanged;

            //start the BackgroundWorker
            worker.RunWorkerAsync();
        }

You might notice that I created a loop that runs up to 100. This is necessary for my solution, as this is the key to make the BackgroundWorker cancelable in my solution. Every 50 milliseconds, the CancellationPending property gets checked as I am looping through until the count reaches 100.  I am setting an offset of 50 milliseconds, as I want to have a total offset of 5 seconds.

Next, let us set up a button that cancels the background task (can be used in other events/methods, too):

public void CancelButton_Click(object sender, RoutedEventArgs e)
{
    //check this always to avoid InvalidOperationExceptions
   if (worker.WorkerSupportsCancellation == true)
   {
         //request cancellation of the BackgroundWorker
         //this sets the CancellationPending property to true
        worker.CancelAsync();
    }
 }

Important: Always check if the Cancellation is supported by your BackgroundWorker to avoid those ugly InvalidOperationExceptions. Then, simply call the CancelAsync() method of your BackgroundWorker to set the CancellationPending property to true.

When the BackgroundWorker has completed (or cancelled), the value of the CancellationPending property is passed to the RunBackgroundWorkerCompletedEvent, where you can simply use the e.Cancelled property to continue your code (which will then be back on your main application thread):

private void worker_RunBackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled == true)
    {
       //your code in case the BackgroundWorker was cancelled
    }
    else
    {
       //your code in case the BackgroundWorker was running until the end
    }
}

The last event I want to mention is the ProgressChanged event. It can be used to display a percentage or similar things, I just use it to see when the cancellation gets active:

private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
     //your code here, for example display percentage or fill a progress bar

     //use the line below to check the percentage and if CancellationPending property gets changed
     //Debug.WriteLine(e.ProgressPercentage + "  " + worker.CancellationPending);
}

With this few methods we can create a time based  offset on a BackgroundWorker while keeping it cancelable at any time. The code above  should work in similar form also on other platforms like Windows 8 or Xamarin.

As always, I hope this will be helpful for some of you.

Happy coding!

Comments 1
Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Prev
AppAdditives PromotionalCodes, Telerik trial reminder and how to let users unlock the full app on Windows Phone

AppAdditives PromotionalCodes, Telerik trial reminder and how to let users unlock the full app on Windows Phone

Next
How to use Text to Speech to read text aloud on Windows Phone 8

How to use Text to Speech to read text aloud on Windows Phone 8

You May Also Like

This website uses cookies. By continuing to use this site, you accept the use of cookies.  Learn more