I want to thank everyone who attended my sessions at the So Cal Code Camp in Los Angeles, CA and at the Desert Code Camp in Chandler, AZ. As I mentioned, I take the questions that come up in my sessions and look into them further. Here's the good news: I have some answers for questions that came up regarding the BackgroundWorker Component. (If you want to take a look at the session walkthrough and code download, you can get them here: Keep Your UI Responsive with the BackgroundWorker Component.)
Passing Additional Data During Progress Updates
Question #1: What is the "UserState" property that shows up in the ProgressChangedEventArgs?
Question #2: Is there a way to pass data from the background thread to the UI thread?
Answer: As you might guess since I grouped these questions together, the UserState property can be used to pass additional information from the background thread to the UI thread during the ProgressChanged event.
As a reminder, we call the ReportProgress method in the background thread which then fires the ProgressChanged event on the UI thread. In the sample code, we used the ReportProgress method that takes a single integer paramter (the percentProgress). But there is an overload that takes both a percentProgress and an additional object parameter called userState. As you might imagine, this will populate the UserState property of our ProgressChangedEventArgs. Let's take a look at updating our application.
First, on the background thread, we will add an additional "update message" where we calculate the progress and call ReportProgress:
This "update message" will contain a string such as "Iteration 45 of 150".
Next, we'll use the new UserState to update the text in our output box:
And here's the output from the running application:
As you can see we have now passed some relevant information from our background thread to our UI thread. It is easy to imagine several uses for this type of behavior. For example, if we were downloading multiple files, we could show the name of the current file in the UI. In addition, since the parameter and UserState are of type "object", we can put anything we want in there, including complex types or collections of complex types.
BackgroundWorker and MVVM
Question: The BackgroundWorker component can be used with WPF and Silverlight. Does this mean that it can be used with MVVM (Model-View-ViewModel)?
Answer: I've thought about this one quite a bit. The question isn't just can the BackgroundWorker be used with MVVM, but whether it makes sense to do so. I've decided that the answer is yes, it does fit in with MVVM.
In the MVVM pattern, the UI elements on the screen (the View) are data-bound to properties and methods in the ViewModel. The ViewModel is responsible for making data from the Model available to the View. In this situation, we would place the BackgroundWorker in the ViewModel. If we were to convert our sample application to MVVM, we could imagine a property for the percent complete that would be bound to the progress bar, and a property for the output that would be bound to the output text box.
The BackgroundWorker would live in the ViewModel and kick off the long running process in the background. When the ProgressChanged event fired (in the ViewModel), it would update the percent complete property (which would in turn update the View due to the data binding). The same would be true of the output property. This would prevent the ViewModel (and the View) from "hanging" while waiting for the long-running process to complete.
MVVM is a much larger topic, and there are a variety of different ways to implement it. But it seems like the BackgroundWorker component may be a useful addition when we are making sure our UI stays responsive.
Again, thank you for the great questions. I hope that I'll see you at one of my sessions in the future.
Happy Coding!
No comments:
Post a Comment