I am building a monitoring application. Data is presented to a user in a girdview. This data changes frequently(an application adds 5-6 entries every second). Total number of entires loaded may be a few thousand.
What is the best way to load these rows into gridview?
Should I load data incrementally? And add each row manually?
Or
Would calling DataBind again be too expensive?
I have noticed a flicker on screen with this approach and so don't want to use this.
Are there any better methods to populate a gridview with incremental data?
I am building a monitoring application. Data is presented to a user in a grid view. This data changes frequently(an application adds 5-6 entries every second)
Can the human eye catch 5-6 updates a second? I think your good with one
update every 500 ms.
Performance tips:
Use BindingList or List. Stay away from datatable/dataset.
Maintain a cache of all the updates. Use a timer with 500 ms
interval, update the List datasource from the cache when interval elapses.
Refresh the CurrencyManager and do not rebind the grid.
CurrencyManager currencyManager = (CurrencyManager)this.BindingContext[Grid.DataSource];
currencyManager.Refresh();
I think loading data incrementally is much better option, and especial suits monitoring application.
Related
I have rapid incoming data (which are basically rows of a tabular data set). As i receive these rows, I merge/upsert them into the data cache. The data has to be shown on a WPF control (an item control).
The problem :
The data is not directly bound to the user control. A series of filter and grouping/aggregation (done using LINQ) is applied on the data before it is shown to the data. Thus what the user sees on the control can drastically change (say he changes the grouping, then all the rows will change).
This is what I am doing as of now :
As the data is coming in VERY rapidly, a thread is picking up the data every 2 seconds, applying the filter and then grouping the data and binding the data set to the wpf item control.
This is definitely not good as a new data table is being set as the datasource every 2 seconds. The application becomes laggy after some time.
What will be the best approach for me to solve this problem ? Thanks.
I'd say the best way to approach this would be to create a view source and bind the display element directly to that - that way you've got the grouping and filtering systems using the built in stuff.
I'd also then look into virtualisation and optimisation which will help with showing a lot of data.
As a more general note, I'd say explore whether you really need all that data to be displayed and at that frequency; it might be a better user experience (and easier on the machine) to aggregate the data and just surface pertinent details, that the user can then drill-down into further as required.
On a winform application,I've the following scenario:
A socket receives data with high frequency (150-200packets x second )
I've a grid view that is populated on the decoded packet received
the received item can be a new item or an update of a previous one..there're 5possible value that can be updated
the gridview is in virtualization mode : on
Since I can't bind to a BindingList (it will freeze the Ui thread) I've decided to use a Queue and to update the grid view based on a Timer. When the timer's elapsed event is processed I update the gridview calling the
gridview.TemplateMaster.Refresh() causing the cellValueNeeded to be called
This is the fastest solution I've found but I have some problems:
I can't know which column has been updated
Using the virtualization on cause me to call the cellValueNeeded each time and my List is almost useless, I can use it as a bi dimensional array
I've to custom implement sort/filter/column reorder
Anyone of you has got a better approach ?
Thanks
I would also recommend having a look at this article: High Performance with RadGridView and Virtual Mode including Filtering, Sorting and Grouping
Given the following additional information:
I've got 8 columns... the row number depends of which item is dragged
from a treeview... in this test case I've got 256 rows but can be more
...for the second point If I rebing the whole itemsource I loose what
has been updated
your issue is much more complex than your OP suggests. You actually have two sources of changes that modify the grid and the underlying data. One is from your incoming data packets and the other is the user. You also have 8*256=2048 items to show the user. That is a lot. And from my understanding of th OP the UI can potentially be updated with as much as 1,000 new values every second. This is not a useful feature since no human being can process information that quickly.
So, given the fact that the user can arbitrarily pull in data into the grid from a tree view and your packet receiver could add or update a thousand cells of grid data per second I would suggest a very different approach:
Keep the queue collection that holds incoming data
Add three new pieces of UI just above the grid:
A read-only control (simple label control would do) that displays the count of updates currently in the queue
A time-stamp of when the grid was last updated from the data packet queue
A button which the user would hit manually to pull in the queued data. Clicking the button would reset the time-stamp to the current time and the count of queued items to 0
You could also keep your timer to automatically update the data but make it smarter:
Extend the time period between automatic updates
Reset the timer whenever the user interacts with the UI at all (this would basically create a situation where the grid is automatically updated only when the user is "idle", or not interacting with the UI)
The columns being moved around is not a problem since you can find/and refer to columns by their column name rather than their index
Since the grid can be sorted arbitrarily by the user you need to use a find function to identify the row to update. You should have some sort of (primary/unique) key column, visible or hidden, by which to identify a row and the underlying object
All other functionality stays the same
Original answer for posterity:
I suggest creating a new collection which would be a shared resource between the UI and your socket thread (assuming you have a thread for the socket communication). You would update this collection as well as a flag time-stamp of the latest change. This flag is important because you would not change it unless data did actually change. You could also have an additional field which could count the number of updates since the latest change. (I'm assuming/hoping that much of this data coming in would not actually be different.)
So now you have an internal cache that can be shared by both threads. You don't have to worry about synchronization issues because one thread only writes and the other only reads.
In my WPF application, I've got a screen with a tab control. Five of these tabs contain datagrids which need to display a large number of rows (at least 5000). The tables are bound to ObservableCollections of Part objects. Each row displays around 20 points of part data. My problem is that, after the user enters the information they require and generate the data, clicking on a tab causes the application to hang for 30-60 seconds. After this the datagrid finally loads, and with the right virtualization settings, they perform at an acceptable rate (not exactly fast, but not too slow). If I disable virtualization, the program uses up way too much memory, and the loading time isn't really affected.
The most offensive tables consist of about half a dozen template columns. Each template contains controls inside a stackpanel or a grid; basically each row is split into two, like a double-row. This layout is a requirement, and paging is probably not something that the customer is willing to accept.
This is the most important screen in my application and I'm pretty much at a loss about making this work. Is there anything I can do to speed up this process? Perhaps ObservableCollection is the wrong choice?
Can you please provide more insights...
Can you check how much time is spent in "generating" the 5 collections of 5000 rows each? (this is what I assume you are saying)
With virtulaization "on" what is the UI loading time "after" we assign the collection to the items source?
What happen if you bind "ItemsSource" to the respective datagrid only when the tabItem is actually Visible \ Selected?
Do you datagrids have default sort member path? Grouping? Filter Paths?
These are a few things I would target to start on the issue.
I have to display information in datagrid some information is about 1000 record from the database (sqlserver) but to display this information c# take unless 4 sec to do that ….
And how work with the application when he don’t see the result immediately he continue to press the button and the application repeat the same function many time due to that (sad) …
I make a break point the time is between the end of the function and the display of window or datagrid … are that normal !!!!
If yes there’s any solution to display a part and when he use the scroll the datagrid add another part (like facebook) ??
The best solution is to implement paging. There is an article at http://www.eggheadcafe.com/tutorials/aspnet/8a2ea78b-f1e3-45b4-93ef-32b2d802ae17/wpf-datagrid-custom-paging-and-sorting.aspx that covers it.
Regardless, make sure you disable the button until the grid has finished displaying, and show a wait cursor as well. A user should never have to wonder if the application is working or failing.
I've seen that happen too - when loading a large amount of data, the grid can take a few seconds to bind to the datasource, making the UI appear to freeze. You'll need to look up info on paging data in WPF, such as this link:
http://social.msdn.microsoft.com/Forums/en/wpf/thread/f72b38f1-38d6-4894-ab86-9a2e5ab5cdac
I have a DataGridView with about 400 rows and 10 columns. When the user first displays this table, it receives all of the data from the server and populates the table. The DGV uses a DataTable as it's data source, and when updating the DataTable I use row.BeginEdit/EndEdit and acceptChanges, but when the View itself is updated it lags for a second while all of the DGV is being updated. I am wondering if there is a way to make this smooth, so that for example, if the user is scrolling through the data and it updates, it won't interrupt the scrolling. Or if the user is moving the display around the screen and it updates, it won't interrupt. Is there an easy way to do this? If not, is there away to prevent the DGV from updating the view until all events have ended so it won't be repainted until the user stops scrolling, dragging, etc ?
In the past I've found that slowness issues can be related to the auto-sizing properties. Here are some more ideas as well: Quick fixes for slow DataGridView
The first idea that comes to my mind is to use a BackgroundWorker. Then, while your BackgroundWorker updates, it doesn't occupy the main thread, that is, your GUI thread.
Try running debugger/profiler to determine which part is the actual cause for slow down. Once you figure out which line(s) are the culprit it will be easier to answer this question.