How to send progress updates from a business / model class?

Say we have a multi-tier architecture application. In the view, we use MVC or MVVM. The model is considered as a domain; it has a significant part of the business logic.

Now let's say that we have a method in the model that takes some time. A complex calculation or processing that must be performed for each element of the object, for example.

In the user interface, we would like to display a progress bar and text that will display the current calculation step (for example, a list with the entire history of the process).

How do you do this? How to send information from the model about the progress of the process and how to connect a controller or ViewModel so that it updates the course?

+7
source share
5 answers

I often implement this as follows. The process of my business level, which takes a lot of time, triggers events so often that indicates that it is gaining specific β€œmilestones”. You decide which milestones should signal events and how many of them. If your time-consuming process is a simple cycle, you can, for example, select the same event again and again every 10% of the elements in the cycle. If it is a process with different phases, you can select a different event at the end of each phase.

Now your presentation level subscribes to these events and acts as a result, updates the progress bar, text, or something else.

This mechanism is good because:

  • The business level does not depend on what can be displayed at the presentation level.
  • Easily extend to bidirectional communications. You can easily change events so that the presentation layer (or any other subscriber) can return the cancel flag so that the business layer knows that a lengthy process needs to be canceled.
  • It allows either synchronous or asynchronous operation. That is, you can use it when blocking calls (i.e. your presentation and business layer share the same thread) or non-blocking calls (i.e. your business layer using the background thread). The System.ComponentModel.BackgroundWorker class can be used in the latter case, but it is not too good if you want to raise several types of events.

Hope this helps.

+5
source

I would recommend looking at the BackgroundWorker class specified in the System.ComponentModel namespace.

The background worker provides the methods necessary for intensive work in a separate thread and receive status updates on it (via ReportProgress , ProgressChanged and RunWorkerCompleted ).

I personally personally experimented using BackgroundWorker in a web environment to run scheduled tasks. I decided to publish the work that I have done so far on Codeplex. I feel that the spirit of my code can be useful for your situation. Codeplex project for web-based task scheduler .

If you decide to download the project, you will see how I use the BackgroundWorker class in the ScheduledTaskRunner class. My implementation does not add progress events to employees, but it would be very easy to do so. In addition, my current implementation focuses on the task at a given interval, but changing it for most of the on-demand processing queue would not be very difficult. I can even add this as a function now that I think about it :)

Assuming you followed the approach to my code above, it would be easy to create an action on your controller that was fired to check the list of "tasks" (or the specific task that interests you), and report the information as a kind of ActionResult . Set up some javascript to poll the action for the specified interval, and you will have progress!

Good luck and let me know if you have questions about my code.

+2
source

Based on your other comments, you are trying to simplify your business level as much as possible.

Then the Model View ViewModel approach can match: http://en.wikipedia.org/wiki/Model_View_ViewModel

As the calculation progresses, you are throwing events that have been achieved.

These events fall into the ViewModel, and the number of changes is updated.

Then the view is updated due to data binding between ViewModel and View (observer pattern)

+1
source

You will need to study the observer pattern (http://en.wikipedia.org/wiki/Observer_pattern). This is a fairly common approach for desktop applications. This is a little harder for the web. You can also look at Comet [http://en.wikipedia.org/wiki/Comet_(programming]] to see how this is done for the Internet.

0
source

In such a case, I applied the following approach. This look has an action that can take a lot of time, and I would like to periodically show progress. Long action is transferred to another class - Worker. Some user actions trigger a DoSomething call in TestViewModel.

Testview.xaml

 ... <!-- Progress bar --> <ProgressBar Visibility="Visible" Height="10" Value="{Binding SomeValue}"/> ... 

TestViewModel.cs extends BaseViewModel, BaseViewModel only implements INotifyPropertyChanged

 ... private void DoSomething(){ Worker worker = new Worker(); worker.ProgressChanged += new EventHandler<WorkerEventArgs>(OnProgressChanged); worker.Start(); } private void OnProgressChanged(object sender, WorkerEventArgs args){ SomeValue = args.Progress; } private const String SomeValuePropertyName = "SomeValue"; private double someValue; public double SomeValue { get { return someValue; } set { if (someValue == value) { return; } someValue = value; NotifyPropertyChanged(SomeValuePropertyName); } } ... 

Worker.cs

 ... public event EventHandler<WorkerEventArgs> ProgressChanged; public void Start(){ //This will take a long time. Periodically call NotifyProgress } private void NotifyProgress() { if (ProgressChanged != null) { double progress = ...; //calculate progress ProgressChanged(this, new WorkerEventArgs(progress)); } } ... 

WorkerEventArgs.cs

 public class WorkerEventArgs : EventArgs { public double Progress { get; private set; } public WorkerEventArgs(double progress) { Progress = progress; } } 
0
source

All Articles