Showing posts with label BackgroundWorker. Show all posts
Showing posts with label BackgroundWorker. Show all posts

Wednesday, March 2, 2016

Testing with the BackgroundWorker Component

I recently received a question regarding how to test code that uses the BackgroundWorker component:
I am trying to write tests using NUnit on an application utilizing BackgroundWorker. I have gone through your course and read some of the articles on your blog. I am wondering if you can give me any suggestions on how to do so?
So let's explore this.

The code shown in this article is available on GitHub: jeremybytes/testing-backgroundworker-component. Specifically, look at the 01-IntegrationTests branch.

Application Overview
We'll start with our sample application that uses the BackgroundWorker component. Here's the functionality.

Application start:

Fresh Start
Initially, the "Start" button is enabled, and the "Cancel" button is disabled.

When we click the "Start" button, it kicks off our long running process (using the BackgroundWorker component).

Process Running

Here we can see the process running. The progress bar is updating, and we have a message "Iteration 21 of 50" that tells us how far along the process is. In addition, we can see the "Start" button is disabled, and the "Cancel" button is enabled.

If we let things run to completion, we get this output:

Process Complete
The "Output" has our final value (which should match the "Iterations" value), and our "Start" and "Cancel" buttons are reset to their initial states.

Our background process only does one thing in our sample: it pauses for 100 ms. This means that if we have an input value of "50", our entire process takes 5 seconds (5000 ms) to complete.

If we press "Cancel" partway through the process, we get this output:

Process Canceled
All of these UI elements are data bound to properties in a view model. This gives us a separate class that is easier to test.

Code Overview
We won't look at all of the code here; just the parts that we need to look at for testing. For a full overview of the BackgroundWorker component and how it helps us offload work to another thread, take a look at the walk-through and articles online: Keep Your UI Responsive with the BackgroundWorker Component.

For more information on using the BackgroundWorker component with the MVVM design pattern, take a look a this article: BackgroundWorker Component and MVVM.

If you'd prefer a video overview, you can watch my Pluralsight course: Introduction to the .NET BackgroundWorker Component.

View Model Properties
We'll concentrate on testing through the view model today. This is the "MainWindowViewModel.cs" file that is part of the "DataProcessor" project (from the GitHub code).

Here are the properties from the view model:


These directly relate to the UI elements.
  • Iterations is databound to the "Iterations" box on the UI
  • ProgressPercentage is hooked up the progress bar
  • Output is databound to the "Output" box
  • StartEnabled determines whether the "Start" button is enabled
  • CancelEnabled determines whether the "Cancel" button is enabled
Because we have data binding in place (along with INotifyPropertyChanged), whenever we update one of these values, the UI elements are automatically updated.

In addition to these properties, there are 2 public methods:


These methods are called when the corresponding buttons are clicked in the UI. The "StartProcess" method kicks off the background process using the BackgroundWorker component, and the "CancelProcess" method lets the BackgroundWorker know that cancellation is requested.

Determining What to Test
When I think about adding tests to existing code, I think about *what* I want to test. Then I can move forward to determine *how* to test it.

In testing the view model, I want to check the behavior of the various methods and how the properties are updated. I test the public members of my classes since this is how my class exposes itself to the outside world.

So I really want to make sure that the properties are getting updated which means that we get the expected behavior from the application. (For the expected behavior, we can refer to the screenshots at the beginning of the article.)

Determining How to Test
Now we have to look at the best way to test this code. Ideally, I want granular unit tests that will verify the behavior of my view model and also the behavior of my background library. Unfortunately, we have some tight coupling between our view model and library, so granular unit tests will require some code modification.

Rather than modifying the code, we'll start out at a higher level of testing. These would be considered "integration tests" because we're really seeing how both our view model and library behave together. The reason that we're starting here is that we can write these tests *without* modifying the existing application.

This will give us a good starting point. Then from there, we can look at what code needs to change to make the unit tests easy to write.

Integration Tests
In addition to the "DataProcessor" project that we saw above, we have a separate project called "DataProcessor.Tests". This is a class library where we've added the NuGet packages for NUnit and the NUnit Test Adapter.

For more information on setting up NUnit and the Test Adapter, you can watch a minute or two of my TDD Basics video: TDD Basics @ 2:55.

Testing Output
Our tests are in the "MainViewModelTests.cs" file. Here's our first test:


The purpose of this test is to verify that the "Output" value is the same as the "Iterations" value if we let the background process run to completion.

In the "Arrange" section, we create an instance of our view model, and then we set the "Iterations" property to 5. As a reminder, we're using the same background library that our application uses. This means that our background process will run for 500 ms (approximately).

In the "Act" section, we kick off our background process, and then we wait. The "await Task.Delay(600)" method will pause operation for 600ms. (And note that since we're using "await", we also need to mark our test method as "async". This works just fine in NUnit and most other testing frameworks.)

This pause is very important. Since our background process is running on a separate thread, our test code will continue to run. Rather that moving immediately to the "Assert", we give the background process time to complete. Having tests with delays in them is definitely not ideal, but this gets us started on the road to testing.

In the "Assert" section, we verify our expectations: that the value of our "Output" (a string) matches the value of "Iterations" (converted to string).

Another Output Test
If the process gets canceled partway through, then we expect that the "Output" property will contain the string "Canceled". Here's a test for that:


For the "Act" section here, we start the process, wait 100 ms, then cancel the process. The reason for the first pause is that we want to give the background process a bit of a chance to run before we cancel it. The second pause (after the cancel) is to give the background process a chance to handle the cancellation request.

Then our assertion just verifies that our "Output" value is "Canceled".

Testing StartEnabled
To make sure that the "StartEnabled" property is getting set appropriately, we'll look at 3 different cases: (1) before the process is started, (2) while the process is running, and (3) after the process is completed.

The first case is pretty simple:


We just initialize our view model and check the value of the property (which should be "true").

Here's are test for the "running" state:


Here we start the process and then wait for 100 ms (reminder, our test case should take 500 ms to complete). Then we verify that the property is "false".

Lastly, we wait for completion:


Just as with our first "Output" test, we wait 600 ms to give our process time to complete. The first assertion (in the "Act" section) is a sanity check to verify the process is complete.

The second assertion (in the "Assert" section) is our verification that the "StartEnabled" goes back to the correct value ("true").

Testing CancelEnabled
The tests for the "CancelEnabled" property look just like the tests for the "StartEnabled" property -- except the expected state is reversed ("true" vs. "false"). We won't bother to look at the tests here, but you can see them in the code project.

Testing Progress
Our tests have been a bit less-than-ideal so far -- I don't like to have delays in my tests, particularly 1/2 second delays (those really add up). But our goal at this point is to get some useful tests out of our existing code.

The last property that I want to test is the "ProgressPercentage" (which is tied to the progress bar in the UI). Unfortunately, our current code doesn't give us enough information to let us know if the progress percentage value is accurate. Calculating that percentage is really a job for the background process, and in a future article, we'll look at modifying the code to make that testable.

What we *can* test with the current code is to make sure that the "ProgressPercentage" property gets updated the correct number of times.

For our test example, we have an "Iterations" value of 5. On each iteration, our progress is updated. Based on that, we would expect that the "ProgressPercentage" gets updated 5 times if we run to completion.

However, the last step of our process is to reset the progress bar back down to "0". So there's actually 1 more update that is part of our process. This means our "ProgressPercentage" should change 6 times in our test scenario.

Tracking Changes
So how do we track how many times a property has been changed? For this, I pulled out the "PropertyChangeTracker" project that I've been working on. This is a helper class that hooks up to the "INotifyPropertyChanged" event. Each time a property is changed, our tracker will know about it.

The existing tracker code knows how to track *when* a property changed. I added a new method to let us know *how many times* a property has been changed:

From the PropertyChangeTracker

This simply counts the number of times that a property name appears in the internal notifications list.

The Test
Here's our test for the "ProgressPercentage" property. This initial test will make sure that the property gets updated 6 times if we let things run to completion:


We have a couple new times in our "Arrange" section. Since set an "expectedProgressCount" variable based on the "Iterations" property. This is the value we will use in our assertion.

Then we create an instance of the PropertyChangeTracker (for details on usage and purpose, see the original article).

In the "Act" section, we reset the tracker. This will clear out any notifications that may have already been received. Then we start the process and let it run to completion.

The last step is to get the "ChangeCount" out of the tracker. We use the "nameof()" expression here to make sure we don't have any typos in our parameter.

In the "Assert" section, we compare our expected value with the value that we pull out of the change tracker.

Progress and Cancellation
There is one more test for "ProgressPercentage", and that's when we cancel the process. Again, since we can't easily get details on progress without cracking open our code, we'll just do a basic sanity check.

If our process is canceled, then we expect that the "ProgressPercentage" property is updated *fewer* than 6 times. Yeah, it's not a lot of information, but we'll go ahead and put a test in for this:


We've seen the various parts in previous tests, so we won't go through them again.

Test Results and Concerns
These tests all come up green with our existing code:


These tests are better than not having any tests at all, and we are able to validate functionality of both our view model and our background library.

But we do have a few problems.

Look at the times. Many of our tests take over 500 ms to run -- this is half a second! Our very small test suite takes 7 seconds to run. The longer our tests take to run, the less frequently we run them.

Look at what we're testing. We're testing *both* the view model and library functions here. That means if one of our tests fail, we'll need to do some digging to figure out what part of the code is actually failing.

Look at the pauses. I really don't like the idea of having "Task.Delay()" in any of my tests. I would rather have tests that rely on something more deterministic (which is one reason why I use the PropertyChangeTracker object in other code). With our tests, they may sometimes fail if something takes a bit longer to run. Inconsistency is not good.

These problems could be fixed by modifying our code and focusing on unit tests

Unit Tests
With unit tests, we're looking at a single piece of functionality and verifying a single assumption. Let's look at a few things we could change to make this code easier to unit test.

First, add an interface for our background library. By adding an interface, we create a "seam" in our code. We can combine this with property injection to make it very easy to replace the real background library with a fake background library that we can use for testing. This would give us better isolation so that we could test our view model independently.

Next, move progress reporting to the background library. In the current code, our calculation of the progress percentage is happening in our BackgroundWorker method (in the view model). This calculation should be moved to the library the BackgroundWorker is calling.

If we combine this with additional progress properties in our library/interface, we can verify that progress is being calculated correctly.

Then, modify the code to make it easier to test cancellation. One of our problems is "start / pause / cancel / pause" in our tests. By adding an interface, we can easily create a fake library that takes no time at all to finish; this would eliminate our pauses waiting for completion. But with a little bit more modification, we can write tests that would verify cancellation without having the awkward pauses.

I'm not exactly sure what this code will look like. It will take a bit of experimentation to make sure that we're eliminating the problems mentioned above.

Look forward to these changes in a future article and a new branch in the GitHub project.

Wrap Up
When we're trying to add tests to existing code, it's often best to take small steps. By looking at what we *can* test without code modification, we can get some of the benefits of automated testing. And some valid tests are better than no valid tests. (Note: having a bunch of invalid tests is *worse* than having no tests at all.)

From there, we can start to look at the shortcomings of the tests we're able to easily make. Then we can think about the tests we really want to write and ask ourselves "Why is it hard to write this test?" From there, we can look at loosening the tight-coupling, breaking out features, and adding bits of information that will make it much easier to write our tests.

My goal is always to have code that is easy to read and maintain and also have tests that are easy to read and maintain. This isn't always something we get to overnight -- especially when we have existing code. But we can take small steps, and we'll eventually get to where we want to be.

Happy Coding!

Monday, October 28, 2013

Shameless Promotion

Three of my Pluralsight courses are currently in the Top 100 as of 10/28/2013 (subject to change):


(I guess there's not much love for the BackgroundWorker Component.) You can see all of my courses in one spot on my author page.

I have more courses coming. If you have topics you'd like to see me cover, feel free to leave a comment. As mentioned before, the topics I select are based on several factors including (1) whether I know anything about the topic (this one is kind of important) and (2) whether Pluralsight already has a course covering the topic.

Pluralsight has over 1,000 courses with a ton of great content. Check the Course Library for some really good resources.

Happy Coding!

Tuesday, August 6, 2013

New Pluralsight Course: Introduction to the .NET BackgroundWorker Component

I'm happy to announce that my new Pluralsight course is now available: Introduction to the .NET BackgroundWorker Component.

The BackgroundWorker component is one of my favorite little tools. It does a great job of keeping the UI responsive by moving a long-running process onto another thread. It also includes progress reporting, cancellation support, and error handling -- all in an easy-to-use package.

Introduction to the .NET BackgroundWorker Component
Keep your UI responsive. If we're not careful, a long-running process will cause our application to "lock up". The BackgroundWorker component gives us an easy-to-use solution by moving that long-running process off of our UI thread. We'll see how the BackgroundWorker component can keep our WinForms, WPF, or Silverlight UI responsive and also explore features such as progress reporting, cancellation, and error handling. After that, we'll see how easily the BackgroundWorker component fits in with an application using the Model-View-ViewModel (MVVM) pattern. And finally, we'll compare the BackgroundWorker component to the Task Parallel Library to make sure we're using the right tool for the job.
After watching this (short) course, you will know everything there is to know about the BackgroundWorker component (yes, it really is that simple). Here are the modules:
  • BackgroundWorker Overview
    Here, we take a look at the problem the BackgroundWorker solves: a non-responsive UI due to a long-running process. Then we see the basics of using the BackgroundWorker component in a WinForms application and in a WPF application.
  • Progress, Cancellation, and Error Handling
    We take a deeper dive into the features including progress reporting, cancellation, and error handling. We see that the component handles communication between the threads for us, so we don't need to worry about those details.
  • BackgroundWorker and MVVM
    How does the BackgroundWorker component fit in with an application that uses the Model-View-ViewModel (MVVM) design pattern? Very well, actually. MVVM applications have the same potential issue (a long-running process that locks up the UI), so we can use the same solution: the BackgroundWorker component.
  • BackgroundWorker vs. Task
    Finally, we replicate the BackgroundWorker component functionality using the Task Parallel Library (TPL). What we find is that all of the functionality is there, but sometimes it's easier to use a specific-purpose tool (the BackgroundWorker) than a general-purpose tool (the TPL).
Lots of great info all in one place. Be sure to check it out: Introduction to the .NET BackgroundWorker Component.

Happy Coding!

Friday, July 12, 2013

I Didn't Expect That

My C# Interfaces course launched on Pluralsight last week.  The interest in the course has been much higher than I expected.  And today, it's showing up at the top of the leaderboard (at least for now):


You can see the live list here: Pluralsight Top 100 Leaderboard.

Helping Developers
The most exciting part of this is how many people are getting benefits from my course. For those of you who've seen me speak in person, you know that I really love to share information with other developers.  What really drives me forward is when I get an email from a dev who tells me that he/she was able to make use of something learned from one of my presentations.  It's also great to get an email from someone on the other side of the world who was able to use one of my articles.

I'm focused on helping developers take a step up.  So, it's very cool to be able to reach so many developers through a single source.

I'm available to help you.  If you're looking for training (single day, multi-day, or ongoing) or for someone to speak at an event such as a "Lunch & Learn", user group, or developer conference, contact me through my website.

Check It Out
If you haven't taken a look at Pluralsight, spend a little time and look through their catalog.  There are hundreds of courses on all different technologies.  If you just browse the categories, you'll see a huge variety to choose from.

Everyone learns best in different ways.  Books are my preferred way of learning.  But some people like blog articles, some people like trial-and-error experimentation, some people like videos, some people like live demos, and some people like one-on-one training.  If you are a "video" or "live demo" person, Pluralsight is a great resource.  They offer a 10 day free trial, and this gives you a chance to check out the quality of the courses for yourself.

More to Come
I'm currently working on my next course about one of my favorite things: the BackgroundWorker Component.  It's a great little tool that's easy to work with.  And even though some people say that it's no longer necessary, it definitely still has its place.

So, stay tuned.  There's definitely more to come.

Happy Coding!

Sunday, January 27, 2013

BackgroundWorker Component Compared to .NET Tasks

There are a lot of questions as to whether the BackgroundWorker component should be used for new applications.  If you've read my previous articles (such as this one), you know my opinion on the subject.  To summarize, the BackgroundWorker is an easy-to-use component that works very well for putting a single method into the background while keeping the UI responsive.

In .NET 4.0, we got Tasks.  Tasks are much more powerful than the BackgroundWorker (orders of magnitude more powerful) and have much more flexibility as well.  In .NET 4.5, we got a way to report progress in Tasks (through the IProgress interface).

A Comparison
Personally, I've been working with Tasks a bit more in my code.  And based on this, I thought I would revisit  my BackgroundWorker sample and rewrite it (with the same functionality) using Task instead.  The result is almost the same amount of code (just a few lines different).  I purposefully wrote comparable code so that we could compare the two approaches.

The Initial Code
Our baseline application will be the BackgroundWorker w/ MVVM project that was reviewed a while back.  This application was chosen as a baseline because all of the BackgroundWorker functionality is confined to the ViewModel (in ProcessViewModel.cs).  This makes it easier to swap out the functionality using Tasks.  I'm only going to cover the differences in the ViewModel here; if you want a better idea of the entire project, see the article mentioned above.  The source code for both projects can be downloaded in a single solution here: http://www.jeremybytes.com/Demos.aspx#KYUIR.

I did make a few updates to the UI.  This is primarily because my development machine is using Windows 8, and the previous color scheme didn't look quite right.  Here is the application in action:


As a reminder, we want to support cancellation and progress (progress includes both a percentage for the progress bar and a message for the output textbox.

So, let's start comparing the code!

Fields and Properties
The Fields of the ViewModel are almost the same.  First, the BackgroundWorker fields:

Now, the Task fields:


As we can see, the difference is that the BackgroundWorker field (_worker) has been removed and a CancellationTokenSource (_cancelTokenSource) has been added.  We'll talk a bit about the CancellationTokenSource in just a bit.  We need this in order to support cancellation of our Task.

The Properties are the same in both projects.  Our properties are used for data binding in the UI (the goo that makes the MVVM pattern work).  Since our UI hasn't changed, the public interface of the ViewModel does not need to change either.

The Constructor
Next, we'll take a look at the constructors.  In our BackgroundWorker project, the constructor sets up our component:


But in the Task project, we don't need this initialization.  We've actually moved some of this functionality down a bit.  But we're left with an empty constructor:


Starting the Process
Now that we've got our basic pieces in place, let's take a look at starting our long-running process.  The StartProcess method is fired when clicking the Start button in the UI.  This kicks things off.

Here is the StartProcess method from the BackgroundWorker project:


And here is the StartProcess from the Task project:


There are several similarities between these.  First, we see that the Output property is cleared out.  Then we see that the StartEnabled and CancelEnabled properties are set -- these properties are databound the the IsEnabled properties of the buttons.  We also instantiate the ProcessModel object (_model) if it has not already been created.  As a reminder, the ProcessModel object contains our long-running process and is the Model part of our Model-View-ViewModel.

Now the differences.  First, notice that we need to instantiate a CancellationTokenSource.  This is the private field that we noted above, and we'll be using this to cancel the process.  We'll talk about cancellation a bit more below.

Next, rather than starting the BackgroundWorker (with RunWorkerAsync), we call a method called DoWorkAsync.  This method returns a task.  We can see that it takes our _model as a parameter (just like the BackgroundWorker), but it also takes a CancellationToken as well as a Progress object.  The Progress object simply implements the IProgress<T> interface, and we'll talk a bit more about this later.

The last piece of our StartProcess method is to add a ContinueWith to our task.  This is the equivalent of hooking up an event to the BackgroundWorker's RunWorkerCompleted event.  When the task has completed, the TaskComplete method will run (and we'll see this below as well).

Cancellation
To actually cancel the process, we use the CancelProcess method.  This does not immediately stop any running processes, it simply sets a flag to indicate that things should be cancelled (if possible).

For the BackgroundWorker, we just call the CancelAsync method on the component itself:


For Tasks, we call Cancel on the CancellationTokenSource:


So, let's talk a bit about cancellation.  For the BackgroundWorker, cancellation is baked into the component, and we just need to call the CancelAsync method.  For Tasks, we need to create a CancellationToken and pass it to the task itself (we'll see how it's used in just a bit).  One of the interesting things about a CancellationToken is that you can't just create one directly.  This is why we have an internal field that is a CancellationTokenSource.  The CancellationTokenSource manages a CancellationToken.  We can use the Token property to get this token (which is exactly what we do in our call to DoWorkAsync above).  We can also set that token to a cancelled state by calling the Cancel method on the CancellationTokenSource.  Notice that we are not setting any properties on the token itself; in fact, we're not allowed to directly update the state of the token.

The Long-Running Process
Now we'll take a look at our long-running process.  This happens in the DoWork event of the BackgroundWorker:


As a quick reminder, this method loops through the Model (which implements IEnumerable).  First, it handles whether the process should be cancelled.  Then it calculates the progress percentage and returns a string for progress display.  Finally, if it gets to the end of the loop without cancellation, it returns the current iteration value.

We'll see that we have very similar code in the DoWorkAsync method in our Task project:


The first thing to note is that we have a custom ProgressObject that contains 2 properties.  This will allow us to report both a percentage complete as well as a message.  Notice that our DoWorkAsync takes a parameter of type IProgress<ProgressObject>.  This lets us know what type of object to expect when the progress is reported.  Note that IProgress<T> is available in .NET 4.5; if you are using .NET 4.0, then you need to report progress manually.

So, let's walk through the DoWorkAsync method.  First, notice that it returns Task<int>.  Because it returns a task, we can use ContinueWith to determine what to do after the task completes -- and this is exactly what we did in the StartProcess method above.

For parameters, DoWorkAsync takes a ProcessModel (our model for doing work), a CancellationToken, and an IProgress<T>.

Since we need to return a Task, we need to create one.  This is done through the Task.Factory.StartNew() method.  The version of the method that we're using takes 2 parameters: a Func<int> (since integer is our ultimate return type) and a CancellationToken.  For the first parameter, we're just using a lambda expression to in-line the code.  We could have made this a separate method, but I included it here so that it would look more similar to the BackgroundWorker version.

Inside the lambda expression, we are doing the same thing as in the BackgroundWorker.DoWork event: we loop through the model.  Inside the loop, we first check for cancellation.  Since we are using a CancellationToken, we just need to call ThrowIfCancellationRequested.  This will throw an OperationCanceledException if IsCancellationRequested is true on the token.  Since we passed the token as part of the StartNew method, the exception will be automatically handled and the IsCanceled property of the Task will be set to true.

Next, we calculate the progress.  The calculation is the same as the BackgroundWorker method.  The difference is that to report the progress, we need to create a new ProgressObject (our custom object to hold the percentage and the message), and then call the Report method on our progress object.

And finally (at the end of the lambda expression), we return the value of the last iteration (an integer).

So, we can see that this part is just a bit different.  It's not really more complicated, but we do need to understand Tasks well in order to get all of these pieces to fit together.

Reporting Progress
Updating the progress bar and message for the UI is similar between the projects.  Here is the UpdateProgress method from the BackgroundWorker project:


As a reminder, the ProgressChanged event fires on the BackgroundWorker whenever the ReportProgress method is called.  The event arguments for the event include the ProgressPercentage (which is an integer) as well as the UserState (an object).  Since the UserState is of type object, we can put whatever we like into it.  In this case, we put a string that is displayed in the output box, but we can put a more complex object in there if we like.

The UpdateProgress from the Task project is similar:


Here we can see that our custom ProgressObject is used as our parameter.  This method is called whenever the Report method is called on the Progress object.  This callback was hooked up when we originally created the Progress object in our StartProcess method:


Notice that when we "new" up the Progress object, we pass the UpdateProgress method as a parameter.  This acts as the event handler whenever progress is reported.

We do get some extra flexibility and type-safety with this methodology.  First, our Progress uses a generic type.  This type is ProcessObject in our case, but if we only wanted a percentage, we could have specified Progress<int> (and not worry about a custom object type).  Because we have a generic type, we don't have to worry about casting and will get compile-time errors if we try to use the types incorrectly.  (For more advantages to using Generics, you can look up T, Earl Grey, Hot: Generics in .NET.)

Completing the Process
Our final step is to determine what happens after our long-running process has completed.  Here is the code from the BackgroundWorker project:


Here, we check for an error condition, check the cancelled state, and have our "success" code which puts the result into our Output box and resets the progress bar.  Whatever the completion state, we reset the enabled properties of our buttons.

And from the Task project:


We can see that this code is almost identical.  Our parameter is a Task<int>.  Since it is a Task, we can check the IsFaulted state (to see if there were any exceptions), check the IsCanceled property, and then use the IsCompleted property for our "success" state.

Should I Use BackgroundWorker or Task?
So, we've seen some similarities and some differences between using the BackgroundWorker component and using a Task.  When we look at the total amount of code, the files are very similar (197 lines of code in the BackgroundWorker and 194 lines of code in the Task).

In writing the Task project, I purposely tried to line up the methods with the BackgroundWorker project.  This was to facilitate a side-by-side comparison.  But using either project, we can reduce the amount of code with lambda expressions and other in-line coding techniques.  But the goal wasn't to create the most compact code; it was to compare techniques.

Advantage BackgroundWorker
The BackgroundWorker component has several advantages for this scenario (and I want to emphasize "for this scenario").  First, the BackgroundWorker is easy for a developer to pick up.  As has been mentioned in previous articles, since the BackgroundWorker has a limited number of properties, methods, and events, it is very approachable.  Also, most developers have been working with events already, and so the programming style will seem familiar.

In contrast, there is a steeper learning curve regarding Task.  We need to understand how to construct a Task (the static Factory is just one way to do this) and how to pass in a CancellationToken and IProgress object.  These are both non-obvious (meaning, I never would have guessed that I needed a CancellationTokenSource -- my instinct was to try to use the CancellationToken directly).  We also need to understand what it means when we pass Tasks as parameters and return values.  So, a bit more effort is required.

One other thing to consider is the cancellation process.  With the BackgroundWorker, we raise a flag and then set the Cancel property on the event argument.  With the Task, the cancellation process throws an exception, and exceptions are relatively expensive.  Unfortunately, throwing an exception is the standard way of making sure the Task's IsCanceled property is set to true.  Since IsCanceled is read-only, it cannot be set directly.  So, we get a bit of a performance hit with the cancellation process for Task.  It's probably not enough for us to worry about in most cases (definitely not in this scenario), but it is something to be aware of.

Advantage Task
Tasks are extremely flexible and powerful.  We only touched on a very small part of what Task can be used for; there is much more (such as parallel operations).  And once we start using Task more frequently we can better understand how to take advantage of the async and await keywords that we have in .NET 4.5.

[Update Jan 2015: If you want to take a closer look at Task, be sure to check out the article series here: Exploring Task, Await, and Asynchronous Methods]

The Verdict
The BackgroundWorker is a specialized component.  It is very good at taking a single process and moving it off of the UI thread.  It is also very easy to take advantage of cancellation and progress reporting.

For this scenario, I would lean toward using the BackgroundWorker component -- this is because I like to use the most precise tool that I can.  And this scenario is just what the BackgroundWorker was designed for.

With that said, I am using Task more and more in my code in various scenarios.  It is extremely powerful and flexible.  I am a bit disappointed to see that Task is not 100% compatible with WinRT (although there are fairly easy ways to go back and forth between Task and IAsyncOperation).  But then again, the BackgroundWorker doesn't even exist in the WinRT world.

Wrap Up
I have a bit of a soft spot for the BackgroundWorker component.  I have found it incredibly useful in many projects that I've done.  And if you are dealing with a situation where the BackgroundWorker fits in, I would still encourage its use.  (If you want to review those uses, check here: BackgroundWorkerComponent: I'm Not Dead Yet.)

But, if you're dealing with a situation where the BackgroundWorker does not fit, then don't try to force it.  Instead, look at how Task can be used to make things work.  And as we use async and await more frequently, understanding Task becomes a critical part to writing understandable and reliable code.

Happy Coding!

Wednesday, May 16, 2012

BackgroundWorker Component and MVVM

As mentioned in the last article, the BackgroundWorker component is still a useful tool for keeping our UI responsive when we have a long-running process, especially when we want that process to interact with our UI (such as through progress notification).  The BackgroundWorker can also work in an application that uses the MVVM pattern for the presentation.  As always, whether it makes sense in your specific scenario will depend on a few different factors.  For our example, we will take the BackgroundWorker sample application that we used to demonstrate the component and modify it so that it is using MVVM.

A few words about the BackgroundWorker component
This article is not designed to teach you how to use the BackgroundWorker component.  You can get an overview of using the component here: Keep Your UI Responsive with the BackgroundWorker Component.  From this link, you can get a walkthrough on using the component as well as the sample code that is used in the walkthrough.

Regardless of whether you are familiar with the BackgroundWorker component, I would highly recommend reviewing the walkthrough and sample code since our MVVM application is based on the original.


The application itself is fairly simple.  We have an input text box ("Iterations") that allows us to enter a number.  When we click the Start button, the BackgroundWorker fires off a simulated long-running process (which uses the infamously slow "Sleep()" method).  The application also has a progress bar and output text box that report the progress of the process.  The Cancel button allows us to cancel the process before it has completed.  The Start and Cancel buttons are enabled or disabled depending on the state of the running process.

A few words about MVVM
This article is not designed to teach you how to implement the MVVM pattern.  We will be looking at *an* implementation of MVVM, but I'm not promoting this as the "best" or "right" implementation (that's a discussion for the big brains who work with this pattern all the time).  I have deliberately kept my implementation simple so that we can focus on the pattern components and how the BackgroundWorker fits in.  As such, I am not using any type of MVVM framework (such as Prism, Caliburn, or the MVVM Lite Toolkit).

For an overview of the pattern itself, you can refer to a previous article: Overview of the MVVM Design Pattern.  For this example, I will be taking an approach similar to Paul Sheriff.  He has several MVVM articles floating around; here is one published in CoDe magazine: MVVM Made Simple.

One thing that keeps this implementation simple is the use of event handlers in the View over using commanding.  If we were to use commanding, we would need quite a bit more code.  The frameworks all provide a messaging system that makes this additional code much easier to implement.  Using event handlers does not "break" the pattern -- as we will see, we will still maintain good separation between our View and ViewModel.

Code Download
The source code for the sample application can be downloaded here: BackgroundWorker w/ MVVM.  The solution contains 2 projects: the original sample ("BackgroundWorkerInWPF") and the MVVM sample ("BackgroundWorker-MVVM").  This allows you to compare the implementations.  Other than moving some code around to fit the MVVM pattern, the core of the projects are very similar.

The Model
All of our business logic should be in the Model -- in our case, that means our long-running process.  The ProcessModel.cs file contains our custom Model: a class that implements IEnumerable<int>.  The idea behind this is that we can use this class in a foreach loop.  The Sleep() method is used to add some time to the iteration.

Because the model implements IEnumerable, we can write code similar to this:


The value that is returned by the iteration is an integer between 1 and the total number of iterations (set in the constructor or through a separate Iterations property).  Since there is a Sleep(100) as part of each iteration, it would take a total of 10 seconds to process 100 iterations.  We definitely would not want our application to lock up for those 10 seconds.

The ViewModel
The ViewModel is where we will find the bulk of our code.  If we were to compare to our original application, all of the code that was in the code-behind (MainPage.xaml.cs) is now in the ViewModel (ProcessViewModel.cs); the exception is the "business logic" that was moved to the Model.

Let's step through the ViewModel so that we can see all of the pieces; these are all in the ProcessViewModel.cs file.  First up are the fields.

Fields
These are primarily the backing fields for our properties.  In addition, we have variables for the ProcessModel and BackgroundWorker.

Properties
Next we have a number of properties.  As a reminder on the MVVM pattern, we should never be updating UI controls directly.  Instead, the ViewModel provides a number of properties that are then data bound to the controls in the View.  We'll see the difference more clearly when we look at a couple of the methods below.  We have 5 properties that will be used for the View: Iterations, ProgressPercentage, Output, StartEnabled, and CancelEnabled.  Here is the Iterations property:


The other 4 properties follow this same pattern.  Notice that the property setter calls the OnPropertyChanged method.  This is because our ViewModel implements the INotifyPropertyChanged interface.  Here is the implementation of the INotifyPropertyChanged interface:


By implementing this interface, we ensure that the data binding on our View will operate as expected.  The controls will be notified whenever the underlying property is updated.

Constructor
The ViewModel constructor initializes the BackgroundWorker component and sets the properties and events:


These are exactly the same properties and events that we set in the original sample.  In the original, we set these in the XAML (since the BackgroundWorker was a resource on the page).  Since the BackgroundWorker has been moved to the ViewModel, we now have to hook these up in code.

StartProcess and CancelProcess
The Start and Cancel methods were button event handlers in our original code.  Since we are moving our presentation functionality to the ViewModel, these now become methods in ProcessViewModel:


I'll point out a few things here.  First, notice that we are setting properties in the ViewModel (Output, StartEnabled, CancelEnabled) and *not* setting UI controls directly.  We are relying on the data binding to get these values to the View.

Next, we are passing the entire Model as a parameter to the RunWorkerAsync() method.  This is slightly different from our original (which only passed an integer).  The change was made to better separate the concerns.  We'll see this more clearly when we look at the DoWork event handler.  Note that we have the check to see if the BackgroundWorker is busy (meaning, the background process is already running) before we perform any work.  We then check to see if the Model has been instantiated.  If not, then we instantiate it with the Iterations property (which is data bound to the UI input box).  If the Model already exists, then we will just update its Iterations property.

The CancelProcess code is exactly the same as the original:

RunWorkerCompleted Event
The RunWorkerCompleted event handler of the BackgroundWorker component has not changed much from the original.  Let's compare the two.

Original Version:

MVVM Version:

The only difference is that we are no longer directly interacting with the UI objects.  Instead of setting "outputBox.Text", we set the "Output" property of the ViewModel.  Instead of setting "IsEnabled" of the startButton and cancelButton, we are setting the "StartEnabled" and "CancelEnabled" properties on the ViewModel.  Again, we are relying on the data binding to handle the actual update of the UI controls.

Note: I simply removed the MessageBox.Show() as it is not appropriate for the ViewModel to directly interact with the UI.  In a more robust application, we would want to have error notification moving through to the View, where the View can decide the most appropriate display for the error.  This is something that the messaging/notification systems in the various MVVM frameworks help us with.

ProgressChanged Event
The ProgressChanged event handler of the BackgroundWorker component is similarly updated.

Original Version:

MVVM Version:

Again, rather than interacting with the progress bar and output text box directly, we are setting properties on the ViewModel.

DoWork Event
The biggest change is in the DoWork event handler of the BackgroundWorker component.  However, this is primarily due to some refactoring work and not simply because we are using the MVVM pattern.  Here is the event handler in the ViewModel:


This is really a combination of the "DoWork" and "DoSlowProcess" methods in the original.  Above, we pass the Model as a parameter to the RunWorkerAsync method.  We can pull this out here from the DoWorkEventArgs.  Because our Model implements IEnumerable, we can use a "foreach" loop on the model itself.  This replaces the "for" loop that we had in our original.

The contents of the "foreach" loop (from the MVVM sample) and the "for" loop (from the original) are pretty much the same.  We check for CancellationPending and WorkerReportsProgress and take appropriate action as necessary.  As a reminder, the "Sleep()" step that was in the original "for" loop has been moved into the model.  Whenever the "foreach" moves to the next item, the "Sleep()" runs in the model.

ViewModel Summary
That wraps up the code in our ViewModel.  If we compare this to the original code, we can see that the BackgroundWorker event handlers are pretty much the same.  The biggest difference is that we added the Properties and code to support data binding to our View.  But overall, large code sections match up from a functional standpoint.

The View
The last part of our MVVM implementation is the View.  This is contained in the MainPage.xaml.  There are only a few changes here -- all to support the data binding to the ViewModel.

Resources
First, we add the ViewModel to the window resources.  This is one way (easy) way to associate a View and a ViewModel.  The various frameworks have different ways of handling the mating of the View and ViewModel.


Here we added the namespace for our ViewModel (xmlns:local), and then added the ProcessViewModel to our resources.  The effect of this is that the ViewModel is automatically instantiated with our View (XAML).  This means that the ViewModel must have a constructor with no parameters (which we do).  Again, the MVVM frameworks offer options for instantiating the ViewModel and passing any parameters (if necessary).

Data Context
We use our ViewModel as the data context for the border which encompasses all of our UI controls:


This makes the properties of the ViewModel available for data binding for all of our controls.

Control Data Binding
As mentioned (several times now), the controls are data bound to appropriate properties in the ViewModel.  Here are the text boxes and progress bar:

Input text box (Iterations):
Progress bar:
Output text box:

For each of these, we can see that the Text or Value property is data bound to the corresponding property in the ViewModel.  The same is true for our buttons:


We have the "IsEnabled" property data bound to the appropriate ViewModel property.  This is how we can  enable and disable the View by setting properties in the ViewModel.

Code Behind
Finally, we have the code-behind for our View.  Notice that our buttons still have Click event handlers.  Here is the total code behind in MainWindow.xaml.cs:


You can see that our code is minimal.  We have a variable to reference our ViewModel.  In the constructor, we populate that variable based on the Window Resource (from the XAML).  Then, for the click event handlers, we simply pass the request through to the ViewModel by calling a corresponding method.

So, although we do not have zero code-behind, we have minimal code-behind.  And in the process, we have still kept our separation of concerns.  The code-behind of the View is not doing any actual work; it is passing the responsibility to the ViewModel.

Wrap Up
What we have seen is that the BackgroundWorker component is still useful in an MVVM world.  If our MVVM sample were to simply "foreach" through our model without the BackgroundWorker, our UI would lock up while that processing was taking place.  But we can still use the BackgroundWorker for exactly what it was designed for: to prevent UI lock-ups.

Our code had to move around a little bit to support the separation of concerns that is described by the MVVM pattern, but our overall code (the moving parts) are essentially the same.

This sample makes it seem like I am a proponent of not using an MVVM framework, but that is not the case.  As I mentioned, the frameworks add a lot of functionality and take away the boiler-plate code that you might otherwise write when implementing MVVM -- especially when writing something larger than this trivial one-screen application.  What I think is most important is that you understand the MVVM pattern before using any of the frameworks.  If you do not have a good handle on the pattern itself, then you may find yourself taking shortcuts that will "break" the pattern.  A strong foundation is essential to make sure that you can use your tools appropriately.

Happy Coding!