Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bulk updates on Complex UI

I have a very complex UI with a constantly changing status bar with multiple types of status messages and UI having a complex chart control and a indicative geographical map loaded.

Now the data context of these small but complex regions have equally complex ViewModels such as StatusBarVM, ChartingVM, GeoMapVM etc... They implement INotifyPropertyChanged and ObservableCollections.

Calculating my updates I see that I have around 5000 UI items (lables, progressbars, chart data points, bgcolorsbrushes etc.) which are changing at a speedy rate of 1000 data item updates per second.

What is the best way to achieve this bulk data update on a WPF UI?

Is WPF's binding model capable for such sort of huge updates? If so how? Because I see it isnt optimum in my case. I am using bgworker (for progressbars) as well and using DIspatcher BeginInvoke... but the point is that even then the updates do hang the UI thread as the dispatcher messages are getting queued up waiting to be finished.

I cannot implement virtualisation as the statuses are real time and I have to see them all on the UI in front of me.. I cannot afford to miss them even by a couple of second (e.g. constaly varying satellite's geographical data).

Please help me to identify a correct tool or some way to achieve a complex but highly responsive WPF UI. Is it Dispatcher.PushFrame()?

like image 216
WPF-it Avatar asked Oct 10 '22 12:10

WPF-it


1 Answers

With that many updates per second, you'll be getting update messages "backed up" in the queue, which is why your background worker updates are getting blocked.

To resolve this, you need to throttle the number of update events being thrown.

I'd use an approach like this:

In my ViewModels, replace the normal implementation of INotifyPropertyChanged with a call to a singleton object that will send the notification on behalf of that object.

private void OnPropertyChanged(string propertyName)
{
    PropertyChangedNotifier.Notify(this, propertyName, propertyChanged);
}

Where propertyChanged is the member variable storing this objects event handlers.

The Notify method would look something like this:

public static void Notify(
    object sender, 
    string propertyName, 
    PropertyChangedEventHandler handlers)
{ ... }

Within the notifier, don't send the event immediately - just store the fact that it needs to be sent.

If you get notified multiple times for the same object/property, discard the extra notifications. If you get notified many times for the same object but different properties, replace the notification with a single one for all properties.

Now, use a UX thread timer to "release" the notifications every 50ms or so - still fast enough that the user won't notice any difference and it looks like real time updates, but slow enough to detect (and remove) duplicate notifications.

like image 173
Bevan Avatar answered Nov 08 '22 20:11

Bevan