1

I have written a WPF app which is now starting to suffer. There is no real way of adding new features to it in it's current state, it has become sluggish to use. This application started as a demo and has unfortunately been sold and then expanded upon (sigh).

At first it was just lots of code all on Main. It was rapidly put together to prove a concept. The application makes API calls and gathers data once per second, the data is then reflected on the UI in a series of fancy looking widgets.

Calling the API from the Main thread once per second was locking up the UI. So this was moved into a BackgroundWorker.

In an attempt to segregate the code, UserControls were created for each widget and the Main is now an aggregation of those. The BackgroundWorker gathers data from the API and then feeds it to the widgets to update the UI.

Because of the BackgroundWorker, non of the UserControls can be directly updated (cannot access controls from a different thread), and everything uses the Dispatcher. The Dispatcher's buffer is getting added to faster than the UI can update, and the data displayed soon goes out of synch and you are looking at old information whilst the app is busy crunching more new data and queueing that on to the Dispatcher.

What would be a more suitable approach. I have some ideas, but as I am not an WPF expert I would be interested in hearing any known good ways to rewrite/refactor this app.

  • 4
    Is this really a XAML-based MVVM WPF app? It sounds much more like Win Forms. – Dan1701 Apr 19 '17 at 17:45
  • 1
    Make no mistake @Dan1701, you can stuff all your code in the code behind in a WPF app just as easily as you can do it in Winforms. – RubberDuck Apr 21 '17 at 1:58
  • Is it fine for data to be skipped if they arrive too fast? Does the update period be constant, or can it change based on how fast UI can display the data? Can the source be queried from multiple threads or does it have to be single thread? Isn't there way to improve performance of updating the UI? Did you profile your application? – Euphoric Apr 21 '17 at 12:22
  • Also, I find it hard to believe the UI would be so complex as to not to be able to update once every second. I would spend some time trying to optimize drawing in your application. – Euphoric Apr 21 '17 at 12:23
  • Is the data for each control same, or are they different? Would it be possible for each component to query it's own data without much redundancy in what data is queried? – Euphoric Apr 21 '17 at 12:26
4

If you really are using WPF, you should probably look into using the MVVM programming paradigm.

First and foremost, you can easily fix updating the UI with most of the functionality in XAML and C# property bindings.

Second, it offers a really large suite of ways to move functionality and business logic away from UI and presentation.

So, with that in mind, you stated you are running into the issue of not being able to update the UI from the Background worker. A common issue.

By utilizing Property Bindings in XAML, the NotifyPropertyChanged Interface of the WPF framework, some delegates or event handlers, this can solve this issue.

How this all works: You have a UI that binds, lets say, a textbox text to a property on a ViewModel class. That property, using the NotifyPropertyChanged Interface, will be what the textbox displays (assuming you use the interface correctly and so forth).

Lets say your background worker does some stuff and makes wants to update that textbox. One simple way would be to have the background worker execute some sort of delegate method to update that property.

Once the property is updated, the property fires the OnPropertyChanged event. That in turn updates the textbox text that it is bound to.

The kicker is, as well, as that a lot of things can be bound to properties, not just text.

Hope that points you in the right direction.

  • 1
    I would also question whether you really need to update every second, or if every 5 or 10 would suffice. Or even if a publish/subscribe tech, like SignalR, would be better. – RubberDuck Apr 21 '17 at 1:59
  • @RubberDuck very true. – Gary.Taylor717 Apr 21 '17 at 2:00
  • @RubberDuck It depends on the type of application. I have written WPF desktop applications that interface to industrial hardware and updates at sub-second intervals (300ms is a good sweet spot for this. And right now I testing some hardware and trying to push updates to sub 100ms - but it gets messy under about 30ms). But your comment implies web based system and I can see nothing in the OPs question that implies that. – Peter M Apr 21 '17 at 17:14
  • That's interesting @PeterM I've done something similar and 100ms does seem to be the sweet spot for updating the screen in real time scenarios. We should trade stories sometimes. – RubberDuck Apr 21 '17 at 18:19
0

Ok, the fundamental problem here lies with the performance of the Dispatcher. If you add things to it too often it can't process the requests as fast as you add them.

I found this excellent resource, which demonstrates my problem in a concise manner and provides three very good solutions which work for me.

http://blog.benoitblanchon.fr/wpf-high-speed-mvvm/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.