views:

344

answers:

3

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?

+3  A: 

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.

Bevan
+1  A: 

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

bleevo
Good answer! I agree and was going to post that until you beat me to it!
BobbyShaftoe
+1  A: 

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.

Jason Jackson