Winforms performance issues

Posts   
 
    
omar avatar
omar
User
Posts: 569
Joined: 15-Oct-2004
# Posted on: 23-Sep-2007 20:56:32   

Some of my winforms have a hefty number of data-bound combo-boxes/List boxes. When the user opens such a form, I usually put the code that populates the binding-sources for these list controls in the form's Load event.

Though this works fine, it does have an annoying side-effect that the form would take noticeable time to open.

I tried many different solutions for this: solution1: 1- Open the form by a routine that invokes the form's "FillLookups" job on a background thread. This helped in keeping the UI responsive while waiting 2- Display a "Please Wait" Box while the form is being opened. This worked but still did not feel quite natural.

Solution2 Another track I opted for is to allow the form to quickly display on the screen (by not handling any lengthy operations in its load event) and then carry out my lengthy processes in the form's Shown event. During the lengthy operation, the form would be disabled (Enabled=false) and it would later on be enabled once the operation is done.

I wanted to probe other workarounds for this issue as I am sure a lot of people have came across it.

mhnyborg
User
Posts: 14
Joined: 26-Apr-2006
# Posted on: 23-Sep-2007 21:58:44   

If the combo data is near static like zip codes and product groups. cache them on the client.

I have code like: FillCombo(this.cboProductType,ProductEntity.ProductTypeId,”NameOfCache”) And a overload: FillCombo(this.cboProductType,ProductEntity.ProductTypeId,”NameOfCache”,DefaultValue)

If the catalog used to fill the combo is not loaded I load it. I have used this approached for to large web sites and the pages loads very fast. I also have a cache refresh interval read from the config file.

Hope this can help you

JimFoye avatar
JimFoye
User
Posts: 656
Joined: 22-Jun-2004
# Posted on: 24-Sep-2007 01:50:30   

I am caching lookup table lists that are not overly big and very stable (usually user can't even edit them at all).

In general, my winforms apps behave like old Vb6 apps at times, I'm afraid. Although, in most other ways, developing for winforms is way better than doing a vb6 app.

omar avatar
omar
User
Posts: 569
Joined: 15-Oct-2004
# Posted on: 24-Sep-2007 08:14:42   

I did implement a caching mechanism in my app but what you guys are recommending is to cache these lists when the app starts and not when a form opens.

I thought of that as during the display of the app's splash screen. The problem here is I am using a custom Principal/Identity object that the BL checks for before retreiving any data. This means I cannot use the splash screen but rather the Logon dialog. The gripe here becomes that a successful logon would take the hit in delay time. But I guess some part of the app has to take this hit..

Did any of you guys get a chance to see SBA (MS Small Business Accounting part of office 2003 and 2007) in action. This is an accounting app build using .NET. It baffles me how MS pulled this thing off using .NET. Data is displayed almost instantly and forms are drawn as if they are hosting a couple of text boxes.confused

stefcl
User
Posts: 210
Joined: 23-Jun-2007
# Posted on: 12-Oct-2007 21:09:59   

Hello, Here's how I do it... There's a form in my app which contains about 15 combo boxes. The form allows the user to edit entities so the combo boxes are essentially a way to select foreign key values without having to type their identifier.

Each combobox has its own datasource. When the form is shown, I don't fill all these datasources with all their possible values but only the values that are currently displayed by the comboboxes. When the user opens the combobox to select a value, the first 50 rows are fetched JIT from the database and displayed (it is barely noticeable). If he starts typing "A", I'll fetch the 20 first records that starts with A to enable autocomplete.

If the user has no idea which value he should type, he can press F4 to open a select dialog where he can navigate and filter the records according to different rules (what SAP does).

Here are the benefits: -A datasource is filled only if its content is actually required. In this case: only when the user is trying to change the value of your bound combobox controls. -The list of value displayed in the combobox is almost never out of date.

omar avatar
omar
User
Posts: 569
Joined: 15-Oct-2004
# Posted on: 13-Oct-2007 06:00:01   

stefcl wrote:

Hello, Here's how I do it... There's a form in my app which contains about 15 combo boxes. The form allows the user to edit entities so the combo boxes are essentially a way to select foreign key values without having to type their identifier.

Each combobox has its own datasource. When the form is shown, I don't fill all these datasources with all their possible values but only the values that are currently displayed by the comboboxes. When the user opens the combobox to select a value, the first 50 rows are fetched JIT from the database and displayed (it is barely noticeable). If he starts typing "A", I'll fetch the 20 first records that starts with A to enable autocomplete.

If the user has no idea which value he should type, he can press F4 to open a select dialog where he can navigate and filter the records according to different rules (what SAP does).

Here are the benefits: -A datasource is filled only if its content is actually required. In this case: only when the user is trying to change the value of your bound combobox controls. -The list of value displayed in the combobox is almost never out of date.

hmmm.. this sounds interesting. Let me see if I get it right; what you are saying that the you are assuming the user would do one of 3 things when dealing with a combo-box: 1- user types in data. If the user types in "K" you would retrieve data starting with "K" and then when user types in "U" you retrieve data starting with "KU". I dont know how fast this would perform but I will sure to try it.

2- user opens the combo list to select a value. In this case you only retrieve the first 50 records. I guess it makes sense here to provide some sort of UI to facilitate paging through rest of data. Also here you are saying that retrieving those 50 records should not be a big performance hit. I guess that makes sense in a WinForms app but I will sure also to try this

3- user needs to search for the value he wants to select from the combo. Here the user F4 to bring up a select dialog. This select dialog should properly facilitate searching/filtering for the data.

Did you extend the combo-box control to bake this behavior in the control or just handled all this per-control. From what I understand so far, your design fits nicely with LLBL's fiterBuckets but I think it will be a headache to implement a UI for the paging functionality in step 2.

I will start applying this to practice and see how it dishes out. Its interesting that you say SAP do this as we are starting a SAP implementation in our company next year. I will sure to keep my eyes open for those SAP combos.

Thanks for the input..

stefcl
User
Posts: 210
Joined: 23-Jun-2007
# Posted on: 13-Oct-2007 13:05:28   

I'll try to answer these 3 points :

1) Exactly, so I can even offer to autocomplete the input. I don't know how big and complex your database is but considering you're only fetching a small amount of data (in my case 20-30 rows from tables which contain 15-13000 records ) it should be really fast.

2) Paging would be an idea but I assume that if the user really doesn't know what he must type then he should use the select dialog instead of browsing all the different possible values.

3) Yes for example if the combo is about selecting a customer, the select dialog offers to filter on country, address or different criterias. Some of these dialogs even allow to add a new records in the db in case the user realizes that he needs a value which hasn't been created yet.

It wasnt very easy to implement, I have created a base usercontrol which holds the combobox and handle all the event-based logic (combo is opened, value is typed, F4 is pressed, selectdialog is returning a value). Then I have created one inheritor per type of data (categories / customers / countries ) and overriden the base methods which query entities from the db. Databinding is then made via a custom property of my usercontrol which allows me to trigger a "select x where id=@value" when the value is set directly by the framework.

I forgot to mention in my last post that I am using devexpress controls but I guess it should be possible to do that with winform standards.

SAP FK fields aren't comboboxes but simple textfields in which you can press F4 to open a select dialog.