ListView - how to avoid twinkling (.NET/C#)? - c#

My application is multithreaded it has f.ex 25 active threads, and each thread pushes it status to list view item by delegate.
example:
private delegate void SetBackColorDelegate(int index, Color color);
private void SetBackColor(int index, Color color)
{
if (listView1.InvokeRequired)
{
listView1.Invoke(new SetBackColorDelegate(SetBackColor), new object[] { index, color });
}
else
{
listView1.Items[index].BackColor = color;
}
}
Depending on status it changes item color and etc. And it twinkles a lot, it looks very nasty :)
Maybe you can suggest how to avoid this ? How to speedup drawing ? Or maybe I should consider of start using some different component ?

While I wait for your response to my comment. If the flickering is a double buffering issue then the accepted answer from this question will get you on your way. Set your listview to use the style from the answer and you're good to go. There is a performance penalty for this since it will ensure that the colour updates only happen in sync with the monitor's refresh rate (normally around 60 times per second), but it will stop the flicking/tearing that occurs when the updates fall between monitor refreshes.

Consider making each thread push its state to some shared data structure, and then poll that once per second from the UI thread using a timer. That way:
You don't have to worry about invoking from the non-UI threads
You won't get a "busy" UI
You'll still be reasonably up-to-date (vs an approach of saying "don't update if I've already updated recently)
I don't know much about UI timers in terms of efficiency - it's possible that such a timer would be relatively costly, so you may need to have some cross-thread communication anyway: make each non-UI thread enable the timer if it's not already enabled, and disable it when you do the update. That way you'll always be a second behind reality, but still with only one status update per second.

Related

Updating UI in realtime

I have to create a WPF UI, which subsribes to real time Fx Rate(Currency + rate) updates and displays them in a grid (roughly 1000 updates per second, which means each row in the grid could get updated upto 1000 times per second).The grid would have atleast 50 rows at any point in time.
Towards this, I have created a Viewmodel which subscribes to the update events, and store those updates inside a concurrent dictionary with key as symbol and value as a RateViewModel object. Then I have another observable collection which has all those rateviewmodel objects, and bind that to a grid.
Code:
public class MyViewModel
{
private readonly IRatesService ratesService;
private readonly ConcurrentDictionary<string, RateViewModel> rateDictionary;
private object _locker = new object();
public MyViewModel(IRatesService ratesService)
{
this.ratesService = ratesService;
this.ratesService.OnUpdate += OnUpdate;
rateDictionary = new ConcurrentDictionary<string, RateViewModel>();
RateViewModels = new ObservableCollection<RateViewModel>();
}
private void OnUpdate(object sender, RateUpdateEventArgs e)
{
RateViewModel exisistingRate;
if (!rateDictionary.TryGetValue(e.Update.Currency, out exisistingRate))
{
exisistingRate = new RateViewModel(new Rate(e.Update.Currency, e.Update.Rate));
rateDictionary.TryAdd(e.Update.Currency, exisistingRate);
return;
}
lock (_locker)
{
exisistingRate.UpdateRate(e.Update.Rate);
}
Application.Current.Dispatcher.BeginInvoke(new Action(() => SearchAndUpdate(exisistingRate)));
}
public ObservableCollection<RateViewModel> RateViewModels { get; set; }
private void SearchAndUpdate(RateViewModel rateViewModel)
{
//Equals is based on Currency
if (!RateViewModels.Contains(rateViewModel))
{
RateViewModels.Add(rateViewModel);
return;
}
var index = RateViewModels.IndexOf(rateViewModel);
RateViewModels[index] = rateViewModel;
}
}
I have 4 questions over this:
Is there a way I can eliminate the ObservableCollection, as it's leading to 2 different datastructures storing the same items - but still have my updates relayed to the UI?
I have used Concurrent Dictionary, which leads to locking the whole update operation. Is there any other clever way of handling this rather than locking the whole dicitionary or for that matter any datastructure?
My UpdateRate method also locks - all my properties on my RateviewModel is read only except the price, as this is getting updated. Is there a way to make this atomic, please note that the price is coming in as a double.
Is there a way I can optimize the SearchAndUpdate method, this is kind of related to 1st. At the moment I believe it's an O(n)operation.
Using .NET 4.0 and have omitted INPC for brevity.
*EDIT:*Could you please help me in rewriting this in a better manner taking all the 4 points into account? Psuedocode will do.
Thanks,
-Mike
1) I wouldn't worry about 50 extra refs floating around
2) Yes, lockless data structures are doable. Interlocked Is your friend here and they are pretty much all one offs. ReaderWriterLock is another good option if you aren't changing what items are in your dictionary often.
3) Generally, if you are dealing with more data more data than the UI can handle you are going to want to do the updates in the background, only fire INPC on the UI thread, and more importantly have a facility to drop UI updates (while still updating the backing field). Basic approach is going to be something like:
Do an Interlocked.Exchange on the backing field
Use Interlocked.CompareExchange to set a private field to 1, if this returns 1 exit becuase there is still a pending UI update
If Interlocked.CompareExchange returned 0, invoke to the UI and fire your property changed event and update you throttling field to 0 (technically there is more you need to do if you care about non x86)
4) SearchAndUpdate Seems superfluous... UpdateRate should be bubbling to the UI and you only need to Invoke to the UI thread if you need to add or remove an item to the observable collection.
Update: here is a sample implementation... things are little more complicated because you are using doubles which don't get atomicity for free on 32 bit CPUs.
class MyViewModel : INotifyPropertyChanged
{
private System.Windows.Threading.Dispatcher dispatcher;
public MyViewModel(System.Windows.Threading.Dispatcher dispatcher)
{
this.dispatcher = dispatcher;
}
int myPropertyUpdating; //needs to be marked volatile if you care about non x86
double myProperty;
double MyPropery
{
get
{
// Hack for Missing Interlocked.Read for doubles
// if you are compiled for 64 bit you should be able to just do a read
var retv = Interlocked.CompareExchange(ref myProperty, myProperty, -myProperty);
return retv;
}
set
{
if (myProperty != value)
{
// if you are compiled for 64 bit you can just do an assignment here
Interlocked.Exchange(ref myProperty, value);
if (Interlocked.Exchange(ref myPropertyUpdating, 1) == 0)
{
dispatcher.BeginInvoke(() =>
{
try
{
PropertyChanged(this, new PropertyChangedEventArgs("MyProperty"));
}
finally
{
myPropertyUpdating = 0;
Thread.MemoryBarrier(); // This will flush the store buffer which is the technically correct thing to do... but I've never had problems with out it
}
}, null);
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate {};
}
Mike -
I would approach this a little differently. You really dont need an Observable Collection unless new Fx rows are being added. Observable Collection as you know only gives you built-in change notification in that scenario. If you have a list of 50 rows (for example) and the Fx object (which represents each individual row) is updated 1000 times a second - then you can very well use the INotifyPropertyChanged on the Fx Properties on the Object and let that mechanism update the UI as they change. My line of thought is - this is a simpler approach for UI updates rather than move them from one collection to another
Now with regards to your second point - 1000 updates in a second (to an existing FX object) - which technically is unreadable from a UI perspective - the approach I have taken is freeze and thaw - which means you essentially intercept the InotifyPropertyChanged (as its firing to the UI) and keep it frequency based - so for example - every 1 sec - whatever my status of all FX objects is (refresh the UI). Now within that second - whatever updates happen to the FX properties - they keep overwriting on themselves - and the latest/correct value when the 1 second interval happens - is shown to UI. That way - data being shown to UI is always correct and relevant when its displayed to UI.
There are a couple of factors to take into account, especially if the number of displayed rates will change dynamically. I'm assuming the 1000 updates/sec are coming from a thread other than the UI thread.
The first is that you will need to marshall the updates to the UI thread - done for you for updates to an existing ViewModel, not done for you for new/deleted ViewModels. With a 1000 updates a second you probably want to control the granularity of the marshalling to the UI thread and the context switching that this entails. Ian Griffiths wrote a great blog series on this.
The second is that if you want your UI to remain responsive you probably want to avoid as many gen 2 garbage collections as possible which means minimising the pressure on the GC. This might be an issue in your case as you create a new Rate object update for each update.
Once you start to have a few screens that do the same thing you'll want to find a way to abstract this updating behaviour out into a common component. Other wise you'll be sprinkling threading code through your ViewModels which is error prone.
I've created an open source project, ReactiveTables, which addresses these three concerns and adds a couple of other features such as being able to filter, sort, join your model collections. Also there are demos showing how to use it with virtual grids to get the best performance. Maybe this can help you out/inspire you.

Proper way of doing Progress Bars C#

I have a big project (30ish developed classes) and I want to make a loading bar for it. I have a current progress and total progress bars. I also have to roughly describe what is happening during the current process.
The way that I did it is manually (haters gonna hate) go through the most greedy process and did estimations of how long it is gonna take (when it is a for loop, just do step ups each iteration).
I read that Background_Worker would be much more smoother, but as I read on, it appeared to me that I still do have to go to every chunk of code and say that I want to increment the progress bar (The idea that I have to do it do describe the process made sense to me).
So my question was: is there a way to sort of encapsulate your method in a "block", which would automatically allocate the progress bar times? Or is there a more efficient way to do what I'm doing?
The best way would be to put your main processing in a different thread to NOT overload your GUI so it doesn't freeze up (user frustration) and then do your progress bar in the GUI thread (or make another thread for the bar, too). All depends on the preference.
But NEVER!! Freeze up the UI. The users just think it is dead and try to force close it.
is there a way to sort of encapsulate your method in a "block", which
would automatically allocate the progress bar times?
No, progress bar is for showing a progress, so you have to set the start, end and current state values form outside (from the caller), because only caller knows what is it going to execute and have, potentially, control over it.
Yes, it is possible, if you visualize infinit bar, that does not provide to a user some quantitative information about action executing, but informs to him, that something is going on. You also can provide some text description, that changes based on current action, so user can see that "something is going on there".
There is nothing worse from UX point of view, then leaving user uniformed, confused in front of the UI that is doing something, which is not clear.
So the both approaches are good, imo.
Perhaps a background worker with the progress bar. Use a global variable to store the progress.
public class SomeClass
{
public int Progress { set; get; }
public void Method1()
{
...
Progress++;
}
public void Method2()
{
...
Progress++;
}
...
}
As each method is called, increment the progress and call the background worker to report progress.
I know there are better solutions to this but this is just an idea.

Updating Text Box

I'm writing a program to help with a game. I need it to update the text box that shows the current exp value, on the forum load it does show the exp, I need it to update the exp like every 3 seconds.
How would I go about doing that?
Here is what I have so far:
Client C = Client.GetClients()[0];
Player P;
P = C.GetPlayer();
expTextBox.Text = ("Experience: " + P.Experience.ToString());
I am not sure if I need a timer (which i have tried and I am very bad at making) or if a backGroundWorker would be best.
Based on your comments, I would recommend that you update your UI when your player/s are attacking, and not use a timer. This will keep your UI the most up-to-date and will probably serve you better than a 3 or 10 second timer. You will have a method like this:
public void Attack(Enemy e)
{
//do your attack code
//did the enemy die?
KillEnemy();
//add exp just for landing a successful attack
AddExp(e);
}
public void AddExp(Enemy e)
{
CurrentPlayer.Exp += e.ExperienceGain;
//update the UI with the new exp
GameWindow.ExperienceBox.Text = CurrentPlayer.Exp;
}
This is of course more pseudocode, because I have no idea what your design looks like, but I've made quite a few games, and this is how I always do it.
Good Luck!
I would encourage you to use Timer if you go to the background worker with infinite loop that is okay but you need to take care of two things when you use background workers:
Updating textbox or any other UI won't work as it needs to be done from the main thread. so you need to check myTextbox.requireInvoke() function before.
Check if the background worker got a cancel signal to exist the infinite loop.
on the other side. you will consume some time when you use timers to update the text box. as the timer would go to the event processing cycle in the windows then fire the event and finally you will write the code in the timer event.

Opening a new thread to do work within GUI class

I am having issues on how to get around the following problem.
I have a class which which allows me to dynamically update and display a graph on a form. In order to update the values of the graph I have a method within the class of the form. I pass in the value to update the graph with to this method. Here is a high level example of what I am trying to do:
class GUICLass : Form {
//Code for drawing chart etc all here
public updategraphWithNewValue(double value){
// Code to update the graph
}
}
My other class is as follows:
class ValueProviderForGraph{
GUIClass graphForm = new GUIClass();
public calculateValuesAndPlot(){
for(int i = 0; i < 4000; i++){
graphForm.updategraphWithNewValue(i);
graphForm.update();
}
}
}
Now the issue I get from the above is that the form freezes while this operation is taking place. How could I go about getting around this, any help or advice would be much appreciated. I hope this high level example has enough information, if not please do let me know and I shall try and explain myself better.
Thanks.
Look into using BackgroundWorker. Its event-oriented interface should get you up and running quickly.
You can only update your form's controls from the thread that the control was originally created on.
If you are trying to update it from a different thread, you must marshal that call. There are numerous approaches on the web. My personal favorite (for WinForms) is the following:
https://stackoverflow.com/a/709846/141172
UPDATE
After re-reading your question at the urging of #StenPetrov, I suspect that you do not have a cross-thread issue after all, but that the UI thread is simply not processing messages while it updates the graph (this would cause the freezing during the operation).
If the UI thread is busy updating the graph, you will get that behavior. However, it looks like you are causing the graph to do an unnecessary update 3999 times. Try moving the line
graphForm.update();
outside of your for loop.
While I don't know exactly how your graph control works, I suspect the call to update() causes the entire graph to be re-rendered. You should only do that after all new data points have been added.
Do you need to update the UI often or not?
If you don't have to update the UI often, such as loading a large graph for viewing, then BackgroundWorker will do.
If you need the UI updated frequently you have to (a) make your graph calculations independent of UI, (b) run the graph calculations in a separate thread and (c) after the update is calculated use Form.Invoke(...) to update the UI

How to do the processing and keep GUI refreshed using databinding?

History of the problem
This is continuation of my previous question
How to start a thread to keep GUI refreshed?
but since Jon shed new light on the problem, I would have to completely rewrite original question, which would make that topic unreadable. So, new, very specific question.
The problem
Two pieces:
CPU hungry heavy-weight processing as a library (back-end)
WPF GUI with databinding which serves as monitor for the processing (front-end)
Current situation -- library sends so many notifications about data changes that despite it works within its own thread it completely jams WPF data binding mechanism, and in result not only monitoring the data does not work (it is not refreshed) but entire GUI is frozen while processing the data.
The aim -- well-designed, polished way to keep GUI up to date -- I am not saying it should display the data immediately (it can skip some changes even), but it cannot freeze while doing computation.
Example
This is simplified example, but it shows the problem.
XAML part:
<StackPanel Orientation="Vertical">
<Button Click="Button_Click">Start</Button>
<TextBlock Text="{Binding Path=Counter}"/>
</StackPanel>
C# part (please NOTE this is one piece code, but there are two sections of it):
public partial class MainWindow : Window,INotifyPropertyChanged
{
// GUI part
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var thread = new Thread(doProcessing);
thread.IsBackground = true;
thread.Start();
}
// this is non-GUI part -- do not mess with GUI here
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string property_name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property_name));
}
long counter;
public long Counter
{
get { return counter; }
set
{
if (counter != value)
{
counter = value;
OnPropertyChanged("Counter");
}
}
}
void doProcessing()
{
var tmp = 10000.0;
for (Counter = 0; Counter < 10000000; ++Counter)
{
if (Counter % 2 == 0)
tmp = Math.Sqrt(tmp);
else
tmp = Math.Pow(tmp, 2.0);
}
}
}
Known workarounds
(Please do not repost them as answers)
I sorted the list according how much I like the workaround, i.e. how much work it requires, limitations of it, etc.
this is mine, it is ugly, but simplicity of it kills -- before sending notification freeze a thread -- Thread.Sleep(1) -- to let the potential receiver "breathe" -- it works, it is minimalistic, it is ugly though, and it ALWAYS slows down computation even if no GUI is there
based on Jon idea -- give up with data binding COMPLETELY (one widget with databinding is enough for jamming), and instead check from time to time data and update the GUI manually -- well, I didn't learn WPF just to give up with it now ;-)
Thomas idea -- insert proxy between library and frontend which would receiver all notifications from the library, and pass some of them to WPF, like for example every second -- the downside is you have to duplicate all objects that send notifications
based on Jon idea - pass GUI dispatcher to library and use it for sending notifications -- why it is ugly? because it could be no GUI at all
My current "solution" is adding Sleep in the main loop. The slowdown is negligible, but it is enough for WPF to be refreshed (so it is even better than sleeping before each notification).
I am all ears for real solutions, not some tricks.
Remarks
Remark on giving up with databinding -- for me the design of it is broken, in WPF you have single channel of communication, you cannot bind directly to the source of the change. The databinding filters the source based on name (string!). This requires some computation even if you use some clever structure to keep all the strings.
Edit: Remark on abstractions -- call me old timer, but I started learning computer convinced, that computers should help humans. Repetitive tasks are domain of computers, not humans. No matter how you call it -- MVVM, abstractions, interface, single inheritance, if you write the same code, over and over, and you don't have way to automatize the things you do, you use broken tool. So for example lambdas are great (less work for me) but single inheritance is not (more work for me), data binding (as an idea) is great (less work) but the need of proxy layer for EVERY library I bind to is broken idea because it requires a lot of work.
In my WPF applications I don't send the property change directly from the model to the GUI. It always goes via a proxy (ViewModel).
The property change events are put in a queue which is read from the GUI thread on a timer.
Don't understand how that can be so much more work. You just need another listener for your model's propertychange event.
Create a ViewModel class with a "Model" property which is your current datacontext. Change the databindings to "Model.Property" and add some code to hook up the events.
It looks something like this:
public MyModel Model { get; private set; }
public MyViewModel() {
Model = new MyModel();
Model.PropertyChanged += (s,e) => SomethingChangedInModel(e.PropertyName);
}
private HashSet<string> _propertyChanges = new HashSet<string>();
public void SomethingChangedInModel(string propertyName) {
lock (_propertyChanges) {
if (_propertyChanges.Count == 0)
_timer.Start();
_propertyChanges.Add(propertyName ?? "");
}
}
// this is connected to the DispatherTimer
private void TimerCallback(object sender, EventArgs e) {
List<string> changes = null;
lock (_propertyChanges) {
_Timer.Stop(); // doing this in callback is safe and disables timer
if (!_propertyChanges.Contain(""))
changes = new List<string>(_propertyChanges);
_propertyChanges.Clear();
}
if (changes == null)
OnPropertyChange(null);
else
foreach (string property in changes)
OnPropertyChanged(property);
}
This isn't really a WPF issue per se. When you have a long-running operation that updates a set of data rapidly, keeping the UI updated - any UI, whether it's WPF or WinForms or just VT100 emulation - is going to present the same problem. UI updates are comparatively slow and complex, and integrating them with a fast-changing complex process without hurting that process requires a clean separation between the two.
That clean separation is even more important in WPF because the UI and the long-running operation need to run on separate threads so that the UI doesn't freeze while the operation is running.
How do you achieve that clean separation? By implementing them independently, providing a mechanism for periodically updating the UI from within the long-running process, and then testing everything to figure out how frequently that mechanism should be invoked.
In WPF, you'll have three components: 1) a view, which is the physical model of your UI, 2) a view model, which is the logical model of the data that is displayed in the UI, and that pushes changes in the data out to the UI through change notification, and 3) your long-running process.
The long-running process can be almost completely unaware of the UI, so long as it does two things. It needs to expose public properties and/or methods so that the view model can examine its state, and it needs to raise an event whenever the UI should be updated.
The view model listens to that event. When the event is raised, it copies state information from the process to its data model, and its built-in change notification pushes those out to the UI.
Multithreading complicates this, but only a bit. The process needs to run on a different thread than the UI, and when its progress-reporting event is handled, its data will be copied across threads.
Once you've built these three pieces, the multithreading is very straightforward to accomplish using WPF's BackgroundWorker. You create the object that's going to run the process, wire its progress-reporting event up with the BackgroundWorker's ReportProgress event, and marshal data from the object's properties to the view model in that event handler. Then fire off the object's long-running method in the BackgroundWorker's DoWork event handler and you're good to go.
A user interface that changes faster than the human eye can observe (~25 updates/sec) is not a usable user interface. A typical user will observe the spectacle for at most a minute before giving up completely. You are well past this if you made the UI thread freeze.
You have to design for a human, not a machine.
Since there are too many notifications for the UI to handle, why not just throttle the notifications a bit? This seems to work fine:
if (value % 500 == 0)
OnPropertyChanged("Counter");
You could also limit the frequency of the notifications, using a timer:
public SO4522583()
{
InitializeComponent();
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(50);
_timer.Tick += new EventHandler(_timer_Tick);
_timer.Start();
DataContext = this;
}
private bool _notified = false;
private DispatcherTimer _timer;
void _timer_Tick(object sender, EventArgs e)
{
_notified = false;
}
...
long counter;
public long Counter
{
get { return counter; }
set
{
if (counter != value)
{
counter = value;
if (!_notified)
{
_notified = true;
OnPropertyChanged("Counter");
}
}
}
}
EDIT: if you cannot afford to skip notifications because they're used by other parts of your code, here's a solution that doesn't require big changes in your code:
create a new property UICounter, which throttles the notifications as shown above
in the Counter setter, update UICounter
in your UI, bind to UICounter rather than Counter
A layer between UI and the library is necessary. This will ensure that you will be able to do interaction testing and also allow you to swap out the library with another implementation in future without much change. This isn't a duplication, but a way of providing an interface for UI layer to communicate. This layer will accept objects from library, convert them to specific data transfer objects and pass them onto another layer which will have the responsibility to throttle the updates and convert them to your specific VM objects.
My opinion is that VMs should be as dumb as possible and their only responsibility should be to provide data to views.
Your qestion sounds similar to slow-down-refresh-rate-of-bound-datagrid.
At least the answers are similar
Have a shadow copy of your data bound to the gui element instead of binding the original data.
Add an eventhandler that update the shadow-copy with a certain delay from the original data.
You need to disconnect the source of the notifications from the target for the notifications. The way you have it set up now, every time the value changes, you go through an entire refresh cycle (which I believe is blocking your processing function from continuing as well). This is not what you want.
Provide an Output stream to your processing function which it would use to write its notifications.
On the monitoring side, attach an input stream to that outputstream and use it as the data source for your UI component. This way there isn't any notification event handling going on at all - the processing is running flat out as fast as it can, outputting monitor data to the output stream you provide. Your monitor UI is simply rendering whatever it receives in the input stream.
You will need a thread to continuously read from the input stream. If no data is available, then it should block. If it reads some data, it should dump it into the UI.
Regards,
Rodney

Categories