Let's say we have an application that has a layered architecture. On the view we use a MVC or MVVM. The model is treated as the domain, it has a good part of the business logic.
Now let's say we have, in the model, a method that takes some time. A complicated calculation or a treatment that has to be done to each items of an object for example.
In the UI, we would like to display a progress bar and a text that would display the current step of the calculation (for example a listbox with all the process history).
How would you do that? How to send from the model the information of the progress of the process and how to hook up the Controller or ViewModel so that it will update the progress?
I would recommend looking at the
BackgroundWorker
class provided in theSystem.ComponentModel
namespace.The background worker provides the methods you need to run your intensive operation on a separate thread, and receive status updates on it's progress (via
ReportProgress
,ProgressChanged
andRunWorkerCompleted
).I actually personally have been experimenting with using the
BackgroundWorker
in a web environment, for the purpose of running scheduled tasks. I decided to publish the work I've done so far on codeplex. I feel that the spirit of my code could be useful for your situation. 'Web Scheduled Task Framework' codeplex project.If you choose to download the project, you will see how I am using the
BackgroundWorker
class in theScheduledTaskRunner
class. My implementation does not attach progress events to the worker, but it would be very easy to do so. Also, my current implementation focuses around running a task on a given interval, but modifying it to be more of an 'on demand' processing queue would not be very difficult. I may even add that as a feature now that I think about it :)Assuming you followed the approach of my code above, it would be easy to create an action on a controller of yours that went fired would inspect the list of 'tasks' (or a specific task you are interested in) and report the information as some sort of
ActionResult
. Setup some javascript to poll the action on a specified interval and you'll have your progress!Good luck and let me know if you have any questions about my code.
You will need to explore Observer Pattern (http://en.wikipedia.org/wiki/Observer_pattern). It's pretty common approach for desktop applications. It's a bit more complex for the Web. You might also want to look into Comet [http://en.wikipedia.org/wiki/Comet_(programming)] to see how it's done for the Web.
I often implement this in the following manner. My business-layer process, which takes a long time to run, raises events every so often to indicate that it's hitting specific "milestones". You decide what milestones to signal through events and how many of them. If your time-consuming process is a plain loop, you may choose, for example, to raise the same event again and again every 10% of the items in the loop. If it is a process with distinct phases, you may choose to raise a different event as each phase is completed.
Now, your presentation layer subscribes to those events and acts in consequence, updating the progress bar, the text or whatever.
This mechanism is good because:
Hope this helps.
I took the following approach to a similar case. This view has an action on it that can take a long time and I would like to show progress periodically. The long running action is pushed down into another class, Worker. Some user action initiates the call to
DoSomething
in TestViewModel.TestView.xaml
TestViewModel.cs extends BaseViewModel, BaseViewModel just implements INotifyPropertyChanged
Worker.cs
WorkerEventArgs.cs
Based on your other comments you are trying to keep your business layer as clean as possible.
Then the Model View ViewModel approach may fit: http://en.wikipedia.org/wiki/Model_View_ViewModel
As the calcualtion is done, you throw events that progress has been made.
These events are caught in the ViewModel, and the progress amount updated.
The View is then updated, due to databinding between the ViewModel and the View (Observer Pattern)