Best way to display realtime queue data from database in grid - sql-server

I have a client-server VB.NET/SQL2008 application which, among other things, keeps track of people who are waiting in a queue. The records for the queue are all updated via the application but they are added/removed on different workstations.
I need to display the queue of people in a grid (could do a multi column listbox if it would add any benefit) and have it automagically update when the queue changes. I don't need it to be real-real-time but I would like the people to show up within a few seconds. I currently have a datagrid bound to the data and I have a timer which is refreshing the datagrid every few seconds. However I'm thinking there must be a better way to do it.
The one thing I don't like is how the grid flickers when it refreshes and if someone double-clicks to select a record exactly as it's refreshing it selects the first person in the list and not the one selected.
I've done some research and it seems like one option is SQL Dependency - however from what I've seen people say it's difficult to set up and get working and "fragile".
Any help is appreciated!

Related

WPF BindingOperations.EnableCollectionSynchronization + ObservableCollection + Reentrancy

Firstly I am terrible at titles and articulating my problem at hand.
I am producing a file-system like structure. Files and Folders are stored in a local sqlite db, you have File entities and Folder entities.
When the screen first opens, goes to the local db and fetches the data and pushes it into the ObservableCollection. This is done on a new background thread.
Here's the problem, if you have 50,000 items, it seems like WPF's new BindingOperation mechanism for cross thread collection access, does some special tricks to queue all the changes to the UI on another thread which then trickles it onto the Dispatcher.
Now obviously I have no control over how it does this. But my question is, how do I handle reentrancy in these scenarios? If the user was to spam-click a reload button that I have, how do I either cancel all these queued UI updates that are slow and pending, or how do I know there's still so many pending UI updates?
It seems rather slow on the updates, with 50,000 items it takes at least a minute or 2 to completely process all items into the list.

Annoying slow responsiveness of form whilst populating combos on background thread

I have a form with 2 tabs. The first tab is boring, the second tab (unseen as default to the user) contains many comboboxes.
Using the FormLoad() event I populate a combobox on the second tab (with around 11,000 items/strings) on a background thread. The sql command to do this is also asynchronous.
Now, in theory this should mean that when the user finally gets round to clicking the second tab (whether that be in 10 seconds or 10 hours) they should be instantly presented with a nicely populated control - but there is ALWAYS a 4 second delay. I just don't get it! If all the heavy lifting is done via the background thread (the whole reason for using them in the first place!), why the heck is my application still slow and unresponsive when the user clicks that darn second tab??!!?!
*Bearing in mind you have to give the application a chance to fill the combo in the first place, plus I know when it's finished populating as the backgroundWorker1_RunWorkerComplete() method fires and sends a debug message to tell me all work has finished.*
Any help will be much appreciated....
11,000 is a lot! The work has been done to populate the comboBox items on the background thread, but the form still has to show all those items. This means the UI thread has to render a proportion of them (or all of them) to the UI (into memory) ready for scrolling; this is what is taking time.
I would suggest overriding the ComboBox control and handling the scroll event yourself. This way you can load a subset of the entire list sequentially when you need them (if that is possible in your case). This will prevent the four second delay you speak of.

Adding controls to winform while allowing user to enter input

I have a WinForms data entry form that will have upwards of 1500 questions. I have the questions broken into sections, and each section will have an unkown number of questions. Each section is its own user control and has rows (2 panels, 2 labels, a textbox, and another user control) created and added dynamically for each question. The section controls are then added to the form.
My problem is that the process takes a lot of time, even with using TPL (Task Parallel Library). I would ultimately like to create/add the controls and allow the user to start entering data at the same time. The controls are going into a scrollable panel. While the user is entering data, that data will need processed on a local database...so more threading could be necessary.
I have tried working with TPL, which I am new to, by having all the controls added to a list during processing and then sorted and added to the form after the Parallel.ForEach was complete...takes about 20 seconds for over 1200 questions.
I also tried utilizing a BackgroundWorker component. Using the BWC seems to be the faster of the two, but there is a race condition for the ProgressChanged() eventhandler and not all controls get added...not to mention the way the form looks with all the rerendering.
Am i just using TPL wrong? What's the best way to go about this? Is there another way or do I just make the user stick out the wait?
Thanks
Am i just using TPL wrong? What's the best way to go about this? Is there another way or do I just make the user stick out the wait?
Most likely, you can use TPL, and get the same response time as BW, but a nicer API for this type of operation.
The trick here is to get a TaskScheduler setup for UI interaction, and then use the Task class to push the controls back onto the UI thread as they're ready. I have a blog post on this specific subject which shows how to get a TaskScheduler setup to use with UI threads.
However, I would recommend keeping these in memory and pushing them in batches, to avoid constantly re-rendering the UI. This is likely to be an issue no matter what you're doing.
That being said - I'd question your overall visual design here - if you're trying to display over 1200 questions to the user, some form of paging is probably a much nicer approach than a huge scrollable container. If you page these, you could load and process the first few (which is probably near instantaneous, since you mentioned you can process about 50 questions/second), and then continue loading the others after the first few questions have been displayed.

Is it possible to refresh a CollectionViewSource too often? Having some strange issues occur

I've got these ListViews bound to a couple of CollectionViewSources. Those are in turn bound to ObservableCollection lists which have plenty of data that updates quite often (it monitors a 32 player game server and displays player metadata and events). I wouldn't ever call Refresh() on the view if it weren't for the apparent necessity to make sure it is continually sorted by Score and to ensure added/removed players are updated on the UI.
Now the issue I've run into is that too many refreshes to the Views will cause them to lose the ability to open a context menu. You can right-click all you want but it will not appear until you destroy the form and re-instantiate it (an unacceptable workaround).
Has anybody ever seen this behavior, and know how to get around it? Initially I was Refreshing as often as it felt it needed to -- this caused the issue almost immediately. I reduced these Refreshes to every 5 seconds and now it happens but not quite as often.
We have had several problems with the CollectionViewSource. It causes lots of performance issues after openening the same window for appr. 5 times. It might be because we were using an LLBLGen collection as items source, but I will never use the CollectionViewSource again.
Now, I wouldn't refresh the view manually. Your ObservableCollection is responsible for updating the data. Try removing the CollectionViewSource for now (so you will lose the sorting ability), and see if the problem still occurs. If it disappears, you will need another way to sort your collection.

WPF: Getting a list box to stay put

I have this situation where I have a ListBox which is being populated from a background thread (it's an address book and the data is coming from AD).
The problem is that since the list is sorted (using CollectionViewSource) and also available to the user while more data is being retrieved, it's bouncing all over the place as new items are being inserted at various places in the list. So it's available to the user, but mostly unusable since the user's selections keep going out of view.
Is there a way to keep Focus to the item selected, and preserve the selection, even if items are being inserted above and below the selection from the background thread? I would prefer not to sort on the server, which I understand can be a bad thing when it comes to AD.
I'm going to respond to this from a UI design perspective rather then a technical code perspective. (I'm sure someone else will have a way to have the list box keep the selected item in view)
I would argue that the use of a list box while large ammounts of data is being added to it is fairly impossible to do nicely. Lets just say you do get it to keep the selection in view, what about while the user is still searching for their required item, you wouldn't be able to keep it still then.
Firstly if the expected total load time is under 10 seconds you could just disable the list box until loading is finished. (Obviously grey it out with a spinning animation or something so the user can see it's doing something.) I'm assuming you have already dismissed this option otherwise you probably wouldn't be asking here. But I do think this is worth considering. If the load time is farily small consider if your users will really gain anything by being able to browse the list while it is still being loaded.
Secondly, I would propose that you find a way to restrict the contents of the list box so that only small quantities are every displayed at one time. You could do this by only displaying names starting with a single letter of the alphabet (along with a letter selection control). Or you could provide a filter entry text box at the top where the user could type the first few letters and the list box would only display the names starting with those letters. This would allow the user to type say "sa" and the list box would display "sam", "samantha", "sacha", etc. Now you only have a small number of items in the list so you don't have to worry about it jumping around. If the number of items in the list grows too large (because of the loading on the background thread) and the list goes beyond the height of the box the user can simply type an extra letter to futher filter the list.
Sorry if this isn't really what you wanted, but I thought it would be worth bringing alternative design up incase you'd overlooked it.

Resources