I have a WPF database viewer application: It's a simple main window containing a user control with a data grid showing the data extracted from an SQLite database.
The problem is that this application takes 6 seconds to start until it is usable.
I tried building the user control (and doing all the data loading) in the constructor of the main window:
The splash screen will be shown 5s this way, then followed by 1s of empty main window until the application is ready to be used.
Users said that it takes too long until something (visually) happens.
I then moved the user control creation (and data loading) into the Loaded event handler of the main window:
The splash screen will be shown 3s, followed by 3s of empty main window until the application is ready.
Users said that it is "better", but don't like the fact that a half finished main window is shown in disabled state for so long.
Is there some general advice to be found about perceived application load time or are there any other recommendations about how this situation can be improved?
I believe ideally the main window would be shown as fast as possible, along with some hour glass or spinner until the data is loaded. But then I cannot just move the user control creation into a background worker as this would be done on the wrong thread.
Does anybody have any suggestions to this problem?
Edit:
Note that right now I've just assigned a LINQ-to-EF query as the grid data source.
One possible improvement may be to load this data into a data table in background and assign it only once loaded...
Edit2:
I'm using .net 4 with System.Data.SQLite and EF4 to load the data. There are more or less 4000 rows and 30 columns.
Load your data asynchronous. Present something nice on the GUI for the user while loading. The following code can help you with this:
BackgroundWorker bgWorker = new BackgroundWorker() { WorkerReportsProgress=true};
bgWorker.DoWork += (s, e) => {
// Load here your file/s
// Use bgWorker.ReportProgress(); to report the current progress
};
bgWorker.ProgressChanged+=(s,e)=>{
// Here you will be informed about progress and here it is save to change/show progress.
// You can access from here savely a ProgressBars or another control.
};
bgWorker.RunWorkerCompleted += (s, e) => {
// Here you will be informed if the job is done.
// Use this event to unlock your gui
};
bgWorker.RunWorkerAsync();
The app is not faster but it seems to be much faster because the GUI is immediately visible and responsive. Maybe you also can show the user a part of the loaded data while loading the rest. Use the ProgressChanged-event for doing this.
Update
I'm not sure if I understand your problem right. If your problem is not the time data needs to be loaded, then something is odd in your application. WPF is IMO very fast. Control-creation does not takes a lot of time. I visualize much bigger lists as you mention in some milliseconds.
Try to look if you have something in your UI that hinders the DataGrid to virtualize the Items. Maybe you have a proplem there. To analyse WPF apps, I can recommend you the WPF Profiling Tools.
The most obvious thing you can do is to profile your application and find the bottlenecks in start up time. It sounds like the most likely culprit will be the loading of data from your database.
One lesson I've learnt is that if you're using an ORM, when loading large datasets if you favour POCO (Plain Old CLR/C# Objects) over ORM-generated database entities (see example below), the load time will be a lot faster and RAM usage will be significantly decreased too. The reason for this is that EF will try to load the entire entity (i.e. all of it's fields) and possibly a whole load of data related to your entities, most of which you won't even need. The only time you really need to work directly with entities is when you're doing insert/update/delete operations. When reading data you should only get fields that your application needs to display and/or validate.
If you follow the MVVM pattern, the above architecture isn't hard to implement.
Example of loading data into POCOs with EF:
var query = from entity in context.Entities
select new EntityPoco
{
ID = entity.ID,
Name = entity.Name
};
return query.ToList();
POCOs are very simple classes with autoproperties for each field.
We usually have repositories for each entity in our applications and each repository is responsible for getting/updating data related to that entity. The view models have references to the repositories they need so they don't use EF directly. When users make changes that need to be persisted, we use other methods in the repository that then load only a subset of entities (i.e. the ones the user changed) and apply the necessary updates - with some validation done by the viewmodel and possibly other validation going on in the DB via constraints/triggers, etc.
There are many reasons for this.
1) Deployment machine might have fairly low configuration.
2) In-Proper or problem with data binding.
Possible solutions would be:
1) Lazy load the data
2) Optimize the performance. http://msdn.microsoft.com/en-us/library/aa970683.aspx
I had saw applications render 5M records less than a second in wpf.
PS:One more least possible reasons may be 30 columns, due to column order access.
Related
I currently use DevExpress controls heavily in an application. The controls are great and speed-up development time dramatically (and hence, I wouldn't want to ditch them) however, I have a few issues with their performance.
My application is a Shell/Modules/Views&ViewModels application (it follows a lot of the design patterns you would find in Prism).
When a view is first loaded it takes an extremely long time to display (on some of my users PCs with slow machines we're talking 5+ seconds of just hanging there). The time it takes apparently depends on the usage of DX controls (how many ones are on there that haven't been seen before by the application).
When you destroy the view and re-open it, it opens in less than a second. The ViewModel in my test cases/performance profiles has been made to re-create each time - so there is no shared state within my code between invocations of the view (no singleton injected objects).
After a bit of discussion and research I appear to have narrowed down the problem to on-demand loading of the template files for the DX controls.
There is a thread here about that:
http://www.devexpress.com/Support/Center/Issues/ViewIssue.aspx?issueid=Q382256
which references:
http://www.devexpress.com/Support/Center/p/B201967.aspx & DevExpress controls for WPF load time
The solution described in these threads is to either display a loading indicator or to use a hidden window with controls on it at start-up. Neither of these options are something I'd like to do (and the hidden window option didn't appear to gain much performance when I tried a simple example, interestingly - which also suggests that I might be missing something).
What I am hoping to do is to pre-load template files that I know I'm going to need on a background thread. Is there any way I can do this in WPF? (I'm thinking this is more a general WPF thing rather than a DevExpress thing - even if it's something that needs to be implemented in the DX libraries themselves).
Any ideas for either me or the guys at DevExpress?
What you can do in the background thread is to preload all the required assemblies. Also make sure they are nged-ed. The UI controls need to be initialized from the UI thread.
I would like to have optimized version of my WinForms C# based application for slower connections. For this reason I wanted to introduce timestamp column into all tables (that change) and load most of things the first time it's needed and then just read updates/inserts/deletes that could have been done by other people using application.
For this question to have an example I've added a timestamp column into Table called Konsultanci. Considering that this table might be large I would like to load it once and then check for updates/inserts. In a simple way to load it all I do it like this:
private void KonsultantsListFill(ObjectListView listView)
{
using (var context = new EntityBazaCRM(Settings.sqlDataConnectionDetailsCRM)) {
ObjectSet<Konsultanci> listaKonsultantow = context.Konsultancis;
GlobalnaListaKonsultantow = listaKonsultantow.ToList(); // assign to global variable to be used all around the WinForms code.
}
}
How would I go with checking if anything changed to the table? Also how do I handle updates in WinForms c#? Should I be checking for changes on each tabpage select, opening new gui's, saving, loading of clients, consultants and so on? Should I be refreshing all tables all the time (like firing a background thread that is executed every single action that user does? or should it only be executed prior to eventual need for the data).
What I'm looking here is:
General advice on how to approach timestamp problem and refreshing data without having to load everything multiple times (slow connection issues)
A code example with Entity Framework considering timestamp column? Eventually code to be used prior executing something that requires data?
Timestamps are not well suited to help you detect when your cache needs to be updated. First off, they are not datetimes (read here) so they don't give you any clue as to when a record was updated. Timestamps are geared more towards assisting in optimistic locking and concurrency control, not cache management. When trying to update your cache you need a mechanism like a LastModified datetime field on your tables (make sure it's indexed!) and then a mechanism to periodically check for rows that have been modified since the last time you checked.
Regarding keeping your data fresh, you could run a separate query (possibly on another thread) that finds all records with the LastModified > than the last time you checked and then "upsert" (update or insert) them into your cache context. Another mechanism with Entity Framework is to use the Context.Refresh() method.
This might be quite complex so sorry for the wordy question.
1) Im going to redesign my application now to work with multiple threads (Backgroundworkers to be precise.) I will probably be having 5 or 6 bgw's for a particular gui. My first issue is, i have one method call that a gui needs to get its "core" data. Various parts of this data is then used for various other calls to places which also forms data that is displayed on the same page as the core data. How can i process this with various background workers such that backgroundworker1 does the core data getting, backgroundworker2 uses a particular item of the core to get more data, backgroundworker3 uses some core data and so on? Thus leaving my gui and main thread in an unlocked state
2) As i said previously, the gui has to get a set of core data first and then a fair few other database calls to get the rest of the important data. As i have seen i need to get this data outside of the gui constructor so there arent such big demands when the gui is created. In a design sense, how should i construct my gui such that it has access to data that then just needs to be displayed on creation opposed to, accessed and then displayed?
I hope these arent too wordy questions? I can see already that a lot of this comes down to programme design which as a novice is quite difficuly ( in my opinion of course). Hopefully someone can advise me as to what they would do in this situation.
Thanks
This sounds like a good task for a work queue. The main idea behind this is to add a work item to the queue, and this work item will have an associated function to do work on the data. The work is typically distributed to any number of threads you specify.
Several of these exist, just google for it.
Have you had a look at the .net 4 Task Parallel Library? Task Parallel Library
Check out the area titled Creating Task Continuations almost halfway down the page.
This is an example form the linked site
Task<byte[]> getData = new Task<byte[]>(() => GetFileData());
Task<double[]> analyzeData = getData.ContinueWith(x => Analyze(x.Result));
Task<string> reportData = analyzeData.ContinueWith(y => Summarize(y.Result));
getData.Start();
System.IO.File.WriteAllText(#"C:\reportFolder\report.txt", reportData.Result);
//or...
Task<string> reportData2 = Task.Factory.StartNew(() => GetFileData())
.ContinueWith((x) => Analyze(x.Result))
.ContinueWith((y) => Summarize(y.Result));
System.IO.File.WriteAllText(#"C:\reportFolder\report.txt", reportData.Result);
Here is the scenerio:
On application open the user is asked to open a "Project"
Inside a project there are processes, categories, tasks, documents and notes.
There are a few more, but lets keep it simple. Most of the items above are lists that are bound to grids or treeviews.
Each of them have a separate database table and are linked with values in the database.
So after a user opens a project I could do something like this:
Get Processes that belong to Project 'A'
Get Categories that belong to each process
Get Tasks that belong to each category
Get Documents that belong to Project 'A'
Get Notes that belong to Project 'A'
and so on
The issue is then if the user closes this Project I have to clear every bound control and clear any variables related, then be ready to open another Project.
So what I am looking for is some advice for the way to handle this type of situation efficiently.
I am using C# .Net, and the application is a Windows Forms application.
Well, any way you slice it, the memory allocations done on load will have to be cleaned up at some point.
Depending on how you do your data access, you may have to do it manually, or .NET's garbage collector may take care of it for you (most likely).
For this type of application (given the limited requirements you've written), I would normally implement it as an MDI application so you could have multiple projects open at once. All of the project loading/disposing code would be run through the child window, so any time a child window is closed, the memory gets cleaned up automatically.
Even if you don't/can't do MDI, I would strongly recommend that you follow the dispose-on-unload model instead of keeping the same form open and reinitializing it with new data. The latter model is very prone to erroneous behaviour because of lingering data and/or state (which is programmer error, but is really difficult or even impossible to track down when trying to reproduce a client's issue). I've seen this pattern a lot in WinForms and it isn't pretty when the form controls and business logic start to get complicated. Dump the form and start again.
so i have a winforms apps that downloads a set of data syncronously on startup. This obviously takes a while but then when any of the services or GUI classes load, they all have this data. I could change this to put on a background thread but then every component that needs access to this data would continuously have to get notified when this data was ready. This seems like bad design for every one of my classes that depends on this data to be loaded to have a If (Loaded) check or have to subscribe to a loaded event . . . any ideas?
Any other ideas?
I've written a number of applications that have similar behaviour to what you describe, and have three suggestions for you ...
Splash Screen
Add a splash screen to your application that displays the status of a number of startup steps. I've used this in the past when an application has a number of steps that have to occur on startup, before the user gets to use the application - confirmation of identity and authorisation of access through Active Directory, contact database for system information, loading static data, initial contact with specified web services, checking that prerequisites (like Crystal reports) are installed and working, etc etc.
Subscription
Have each component register interest with your data loader, and be notified when the data is available. This is the observer pattern, nothing wrong with it, though managing the subscriptions can be a bit messy.
Lazy Loading
Design the rest of your application to request the data as late as possible, giving as wide an opportunity for background loading to complete as possible. Users who are quick off the mark after startup have to wait for necessary data to load; users who take their time (maybe they started the application and then switched to Outlook) find response is immediate.
I would suggest you use the Observer Pattern and setup all the classes that rely on the data set being loaded. To minimize the amount of time the user needs to wait you could also consider implemented two categories of classes those that need the entire dataset to function and those that can function once a subset of the data has been loaded.
Observer Design Pattern
Everything I do in a desktop app, whether it is Winforms or WPF, I try to do on a background thread. This is done for two reasons. First, the user experience is better. Second, in WPF testing I have found it to be a better performer when loading a lot of data, like records into a grid or list.
Loading data upfront vs lazy loading is really a per-application customization. I would build a central data object that handles both scenarios. The way I might recommend doing this is to create an event driven dependency model. What I mean by this is that you can place an event or callback registration function on a data manager object that various units of code subscribe to when they need to use data, and then they are called back when the data are available. If the data are already available then the callback occurs immediately. Else, the code unit is called back when the data are loaded from a background thread. For example, in some window or component you might have some code that looks like:
DataManager.LoadDataAsync(dataCommandPatternObject, CallBackFunction);
...
public void CallbackFunction(SomeDataObjectClass data)
{
//load data into UI
}
If data loading is done through a central mechanism then if the same data are requested twice, a cache version can be used or the second request can wait if the first request is still running.
If data needs to be loaded up-front, a loading screen (splash screen) can request a number of pieces of data, and when each block of data loads a callback is fired. When all the callbacks have fired, the splash screen exists.
These are just a few points from some various techniques I have used over the years to manage the loading of large data-sets of mostly static/lookup data. On top of all of this, I would also recommend some sort of client-side disk caching for very large datasets that rarely change, and implement some sort of change tracking in the database. This would allow this data to be loaded from local disk by the client, which is faster that going to a DB. It also lets the DB scale better, since it is not serving out data that it highly repetitive, and instead it can focus on transactional data.