Optimal Grid update
Hi,
I'm building an application which displays trades for a stock. Each new trade is represented as a new row in the grid. We are seeing some spikes in CPU when there is a burst of trade data which adds several rows to the grid simultaneously. It would be great if you could tell comment on my architecture and suggest the best way for me to leverage Dapfor's performance.
My grid is bound to a thread safe binding list. The grid has 4 columns. As each trade comes in I add it to a local list for caching. Every 16 ms, a timer kicks in which then takes the trade data and creates a model and adds it to the threadsafe binding list. We do a couple of things here
1. When the timer kicks in, we invoke grid.BeginUpdate and start processing ( add objects to the threadsafe binding list )
2. The grid is unsorted, we always add the new object to the top of the list - ( threadsafebindingList.insert(0,newObject) ) . We do this so the newest trade is always at the top of the grid.
3. Call end update when we have finished processing.
All the processing happens on a non gui thread, so we do marshal the begin/end update to the gui thread. We do the grid begin/end update to achieve block updating, so that if there are 10 trades there is only one draw instead of 10 draws, but it seems like it still draws 10 times.
Given this architecture, can you tell us if there are ways we can optimize it.
I appreciate all your help.
Thanks,
Deepak
-
Dear Deepak,
Your architecture is not optimal to get the maximum of performance. Firstly, you shouldn’t call BeginUpdate/EndUpdate because the call of Grid.EndUpdate leads to repainting of the entire surface. Then the BindingList takes a lot of resources especially when you add data to the beginning.
From our point of view when the timer ticks in the GUI thread you should take all newly added trades and add them to the grid directly using Grid.Rows.Add(_data_object_). If there are multiple trades in the cache then all of them should be added in the same timer’s tick. In this case no WM_PAINT messages come to the grid while row adding. When you leave the timer’s handler, the grid will receive WM_PAINT message once for all added trades. Moreover the grid has also internal algorithms to improve performance when bulk rows are added in the GUI thread.
Look at the example demonstrating this approach:
//Initialize GUI timer
_timer.Interval = 15;
_timer.Tick += delegate
{
//Protect the _cache container
lock(_cache)
{
//Copy all objects to the grid
foreach (object o in _cache)
{
Row row = grid.Rows.Add(o);
row.ChildIndex = 0;
}
//Clear the cache
_cache.Clear();
}
};
_timer.Start();Best regards,
Dapfor
0 -
Thanks for the Update. I will try this out and let you know what I see.
0
Please sign in to leave a comment.
Comments
2 comments