Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A MultiProgressViewModel to observe progress in complex algorithms

0.00/5 (No votes)
20 Jan 2012 1  
I have posted a recent article on the ProgressViewModel to show a software design that can be used for background processing in C# 4.0. This article extends that design with the ability to ouput more than one progress.

Introduction

Managing asynchronous tasks and connecting them with a responsive GUI has been a challenge of the past. The arrival of multi-core processors and the Parallel Task library in C# have given us something to improve algorithms towards speed and efficiency. The Async CTP and C# 5.0 are still not in production and it is therefore a worthwhile journey to find a stable ProgressViewModel that can be applied in C# 4.0. I developed this ViewModel in another CodeProject article called A reusable ProgressViewModel to observe progress with MVVM.

This article takes the previously shown design and extends it, such that multiple progresses can be managed within this pattern.

StyleCop

I use StyleCop in my projects to make the code readable in a uniform way. So, if you should get an error when compiling the project, you can either download and install StyleCop, or edit/remove the corresponding entries in each .csproj file:

<Import Project="$(ProgramFiles)\MSBuild\StyleCop\v4.5\StyleCop.Targets" />

Background

I am developing an application where a batch like processing is required. N items are selected and each item is processed (in sequence) in an asynchronously executing thread. To simulate this situation, I have extended the demo application such that not only HTML files in a given directory are parsed but also all HTML files in all sub-directories below the Path directory.

HTMLTitleParser

The progress section has two progress indicators. The n of m label and the progress bar on the right-top side of the MainWindow. The former indicates the directories parsed with the total number of directories, while the latter progress bar indicates (as before) the progress of parsing HTML files in any given directory.

Download the attached SampleData if you do not have a directory with HTML files and sub-directories with more HTML files on your system. Click on the expander in the lower part of the first MainWinidow, point the application to the uncompressed folder, and click the Process HTML button to get some processing going.

Using the Code

The extension of the ProgressViewModel discussed here is (in a nutshell) in the MultiProgressVM class where I replaced the simple properties:

  • ProgressMin
  • ProgressMax
  • ProgressValue, and
  • IsProgressVisible

with arrays:

  • ProgressMin[]
  • ProgressMax[]
  • ProgressValue[], and
  • IsProgressVisible[]

The class constructor accepts an int number which controls the size of these arrays (default is one). The View can then implement multiple progress indicators by binding to an item in each array of properties. I wanted to keep this extension separate from the first approach because I wanted to make sure that we can see the differences afterwards and I would still like to use the approach from the first ProgressViewModel article.

SolutionExplorer.png

A project overview with the Visual Studio 2010 Solution Explorer shows that I added the selected classes in comparison to the previously posted article on the ProgressViewModel.

I added one more class for each object in each layer (except for the View and Result class). This shows, one more time, the layered nature of the architecture used here.

The binding in the View is changed from:

  • IsProgressVisible to IsProgressVisible[index]

to indicate the corresponding item in the array.

A similar change can be seen in the code-behind of the ProcessHTMLDirectory method in the MultiProcessHTML class. Here, a statement, such as:

this.ProgressMax = files.Length;

is replaced with:

this.SetMaxValue(1, files.Length);

to let the bound UI know that these values have indeed changed.

The ProcessHTMLDirectory method in the MultiProcessHTML class iterates through an inner and outer loop. The inner loop goes through each file in a given directory while the outer loop iterates on each directory within the given directory.

There is really not much more to say about this, other than highlighting the above differences and noting that the ProgressViewModel is now managing two progress indicators, where it used to have one. Please make sure that you have read my first article on the ProgressViewModel if you find the above explanation rather too short.

Points of Interest

I was not sure whether arrays can actually be bound to UI elements. The short answer is yes, but we can no longer update values through a CLR property, since C# does not support named indexers, and we are required to execute OnPropertyChanged() when a value changes. So, implementing a separate method per arrayed property and setting the setter of each arrayed property to private has done the trick in my case (and I thought that implementing a separate class with an indexer is besides the point and not worth the effort).

Seeing the new n of m progress indicator makes me wonder about estimation progress indicators of the type: Remaining time: x minutes. One simple way to do this would be to log the time it takes to execute one inner loop and simply multiply the result with the number of inner loops left. This would work well if each loop requires (on average) the same amount of progressing.

It would not work good if the effort required for processing varies greatly from inner loop to loop. Obviously, getting reliable estimates is a separate issue in that case. Maybe this is a topic for an article three in this series...

Please take a moment of your time to give me your feedback as a vote and comment.

History

  • 20 January 2012: First version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here