Facing an issue where in the user objects goes more that 10000 in windows app and the app crashes.
After much analysis we realized that we need to get rid of the panels that we use to align the controls and may be reduce the possibility of user objects reaching 10000.
Our App UI is dynamically generated driven by a configuration and it can vary. So all the UI generation is happening dynamically.
Any help would be much appreciated
This is an unfounded suggestion, but remember to make sure that unneeded Controls always detach themselves from events they are be subscribed to. A Control that's still subscribed to an event of an "active" (what's the right term?) object can't be cleaned up.
Just as a note, the Chrome development team hit this problem too, and the scroll bar arrows (among other things) weren't drawing anymore when some internal gdi limit was hit. It is quite possible to hit this limit in a complex enough gdi app.
You might want to do some research and see how they fixed it.
As an alternative, you could consider using a different platform, either gtk or wpf would do fine and they don't use gdi handles to draw.
from here,
If your program runs haywire, you will
find that it manages to create about
10,000 window manager objects and then
the system won't let it have any more.
Why stop at 10,000?
The first answer is "If you have to
ask, you're probably doing something
wrong." Programs shouldn't be creating
anywhere near ten thousands window
manager objects in the first place.
There is no need for that many handles. I think you need a new solution.
I'm guessing this from your question, but you're probably putting this large number of controls on a scrollable panel or a tab control with multiple tab pages, which means that most of these controls aren't actually visible to the user at any given point in time (because they couldn't possibly all be visible at once).
If you have all of these controls on a scrollable panel, one possible solution is to only load and display the controls that are on the visible portion as the user scrolls around in the panel. As the user scrolls, you would unload and dispose the controls that are no longer visible.
If you have all of these controls in a multi-page tab control, you can use a similar strategy and only load the controls on a tab page when that page is made visible (and unload the controls from the previous top-most tab page at the same time).
Another general strategy is to break up your one monster form into a large number of UserControls, and only show one of these UserControls at a time.
Related
What I need can probably be described as "reverse-anchor", "reverse-dock" or something like that (I have chosen to mention this just because "reverse-anchor" happened to be the first thing to come into my mind as a keyword candidate when searching for questions and answers that might already have been submitted discussing this subject, perhaps this will help people thinking a similar way to find this one in future). WinForms controls implement the Anchor property to set up adaptive resizing on containing control/form size change but I need the opposite - the form to resize adaptively to the controls.
A thing adding a minor bit of complexity to the task is that the controls meant to be added/removed/shown/hidden/enabled/disabled (and resized perhaps - this functionality is not really needed directly so far but I suspect it can turn to be required for compatibility with non-default Windows visual styles and themes that have potential to affect controls sizes unpredictably and can change at any moment of the app running) are not going to be the last ones on the form - a row of buttons will always be in between of the last control of the volatile group and the window lower border.
The actual task is to design a form that will display a collection of objects with a row of controls (a label, a text box and 0-2 buttons) corresponding each of them and it is strongly preferable to use just the very basic "common controls" avoiding grids, lists and stuff like that in this case (wrapping them in an additional container controls like panels is perfectly acceptable though, abstracting them in a separate "user control" can be considered too if this can really make the solution easier, more reliable or otherwise better, using hand-written code manipulating controls and form sizes is perfectly acceptable too (I can hardly expect a "set a magic property and it's done" kind of solution to exist for this task) but I haven't found a reliable algorithm so far (when to change what properties and what formulae to calculate new values with)).
The maximum capacity can be safely limited to something near 10 (or 20, perhaps, but not more - more would be just absolutely unreasonable to display on one form (provided scrolling is not an option)) so both ways are acceptable: to add/remove the controls in runtime or to put them on the form in the designer and just manipulate Visible and/or Enabled properties in the code. By the way I have found a problem with Visible - it gets switched off and back on by the framework internals before the form is rendered and other controls Anchor properties come in the game but I don't think it's a good idea to rely on this to happen always and the same way so just adjusting the form Size property on a control Visible property change does not feel really convenient).
What might be some good ideas relevant to implementing this behaviour?
PS: As far as I know this is a natural feature of WPF but I am to use WinForms to make the app runnable on Macs and, perhaps, other non-Windows platforms with help of Mono.
I'll tell you about some clues may help you:
1- correct to build your own Procedure for manipulating all the matter.
2- i advice to use a Wizard methodology (Next / Back buttons) so if the plate form is small like tablet or smart phone, so the mentioned procedure will decide how many Controls combinations (Label, text box, option button...) will be in each frame of that wizard and keep the remaining for Next button.
3- By the way if you will hide some controls use the original event fires to run the mentioned Procedure. (like a basic button to start the form so don't depend on visible / resize events).
4- Resize the size of each form of the wizard in the last part of the mentioned procedure.
If still a problem exists tell me and i hope i can help :-)
I am working in a Windows Forms application, it needs a lot (and I mean a lot) of controls. Using tab controls to organize them (sometimes nested tab controls).
I was reading how to load the App faster and a lot of people said to think twice if the controls are really needed. Well, to be honest I think that it's possible to reduce the number of controls used BUT the client requested it that way, so there's almost nothing I can do about it.
I was reading that I should use multithreading tactics but there's a hardware limitation: the application MUST run on an average neetbook. It's really a pain because I'm limited in terms of load time and how much space I can use to put the controls.
I was wondering if I can just load one or two tabs before the form is shown and then load the others, would that be possible/correct/efficient? If it is, how could I achieve it? I also was planning to use MDI childs but I need to retrieve all the information in all the controls at some point (from absolutely all the tabs and nested tabs).
Can you please give me some tips? Do you have any experience working on something similar?
One strategy is creating your main page with a TabControl holding empty TabPages.
Then you can design several auxiliary forms (one for each TabPage you require) each containing a single Panel control with Public visibility (change the Panel's Modifiers property to Public) holding the real UI elements that you would have placed on the TabPage.
When the empty TabPage is clicked by the user, then you create the auxiliary Form (you don't show it, just create it), and then access the Panel control in the auxiliary Form, then you can reparent it to your empty tab Page, like this
AuxForm1 frm = new AuxForm1();
frm.MainPanel.Parent = this.tabControl1.TabPages[0];
This will delay the TabPage's control creation until the panel is clicked by the user :)
Hope this helps!
I was wondering if I can just load one or two tabs before the form is shown and then load the others
You could make each "tab" contain a UserControl, and load that UserControl on demand, when the tab is activated. That would, at least, prevent you from having to initialize everything on startup.
"lots of controls" is not a requirement anyone can answer. A dropdown list with tens of millions of rows is a very different problem than a wizard UI with thousands of steps and require different answers.
Why has the client "requested it that way"? We need to know the actual deliverable requirements to answer your question. Have you shown them alternatives?
First, post some of your mockups. If you don't have mockups yet, make some and perform paper testing with them, then post them.
Who's "a lot of people"? Testers? Customers? Anonymous forum posters? Post your mockups to https://ux.stackexchange.com/ and ask for comments.
"I can just load one or two tabs before the form is shown"? Of course you can do that, but why are you presupposing that your UI will be "one or two tabs" before you have shown us any requirements at all? Get requirements, make mockups, then ask specific, answerable questions.
I have a WinForms application. the main form is has a lot of controls and that is one of the reasons that makes it load very slow. what I would like to do is to make the form load faster.
I have set the beginupdate and endupdate. The form is not being rendered in the background worker thread, because this is the main form. There are no initial forms. When the user clicks the application icon, this is the first form that loads up. Adding a progress bar or any splash form is not a good idea for me.
I have checked other questions here on Stack overflow but they do not seem to face the same problem as I do.
If there are some examples/ideas you have in mind, it would be nice of you if you can share it with me.
A few suggestions:
Try to minimise the complexity of your UI. Your users will thank you and you'll have fewer controls to load. For example, if you have 3 or 4 controls that are not used often, can you move them into a dialog or fold-out "advanced" section of your form, so you can defer creating/showing them? Are all the controls needed? Really? Think about the workflow you are trying to achieve - is the current set of controls the simplest way to achieve the workflow? DO all the controls need to be shown at once? Perhaps you could place them on to separate tabs in a tab control (and thus only actuallyl create the controls as the tab is shown)?
Can you reduce the range of control types used? Each new type of control may cause your program to load up a new dll to support it. Every dll that has to be initialised causes extra startup time.
Are you using any controls that are slow to start up? A simple text field will be fast, but a complex graphing control may be slow.
How many assemblies (of your own) are loaded? Combine all the code into a single assembly (e.g. with ILMerge) and load times will probably improve quite a bit.
Remove any initialisation code that isn't needed. Can you simplify the initialisation? Can any initialisation be deferred (e.g. only create some member variables when the user clicks on the first button that actually needs that data to be present, Don't try to create a connection to a database if it's not actually needed yet, etc)
Can you defer creation of (some of) the UI? For example, you may be able to place a group of controls into a separate UserControl form, and then add this form programmatically to your MainForm shortly after startup (e.g. on a Timer). This will allow your MainForm to appear very quickly, and then be "populated" shortly after with additional controls, which may not improve the actual startup time, but it will "feel" a lot faster and more responsive to start up. (This approach can also be extremely effective if your MainForm scrolls and those extra controls are initially not on-screen, as they only need to be created if the user scrolls down enough to see them)
Are you displaying any information that might be slow to load (e.g. large bitmap images or data fetched from an SQL server)? Can you defer the loading of them or run it as a background thread? Use compression to speed up loading? Reduce their resolution to minimise the amount of data that must be loaded? Pre-process data and store it in a quick-start cache for the next time the program is run?
Can some controls be replaced by an optimised approach? e.g. You can create a "button bar" as a set of 10 separate controls, or as a single control that draws iself with the appearance of 10 buttons. It's much easier to make the single control initialise and redraw faster than 10 separate controls.
And of course, once the most obvious low-hanging fruit has been collected (or even before):
Run the program under a profiler and see where it's spending its time.
Try to minimize the code that executes during on load of main form or any of the control that is placed on the main form.
You can also explore NGEN which is Microsoft's tool which helps in improving managed app's performance
When a form loads it initializes all its controls.
The Form itself isn't taking you a long time.. It's your controls.
Go over your controls and check what can be improved in their constructors and initializers.
Do you need all of the controls immediately? If not perhaps you could load them programmatically after some event fires that lets you know you need that control.
If you have several controls to a parent control, call the SuspendLayout method before initializing the controls to be added.
After adding the controls to the parent control, call the ResumeLayout method. This will increase the performance of applications with many controls.
For example:
private void LoadData()
{
// Suspend the form layout and load the data
this.SuspendLayout();
LoadMyData(); // logic to load your data will be here
this.ResumeLayout();
}
EXPLANATION:
SuspendLayout() - Stops the layout object from being updated and thus the component does not spend any time making calculations for repainting until the layout is resumed.
ResumeLayout() - Recomputes the layout once after all of your changes are made, resulting improvement in performance.
Why use SuspendLayout() and ResumeLayout()
It prevents layout accidents when controls have layout properties that affect each other.
It adjusts multiple layout-related properties like Dock, Auto-Size etc.
My form has over 200 control(s)!
It takes about 7 seconds to load the form and bind the controls.
I've traced the application with some performance profilers , but I didn't find anything with HOT flag except the constructor's of form.
I would like to know that is it possible to call InitializeComponent method with sth like backgroundWorker (multithreading) !?
No, threading will not help you. The controls need to get created on the UI thread for the application to work at all.
The only reasonable way would be to look into whether you really need to create all 200 controls when the form is created, or if you can perhaps have them load "on demand".
Without knowing your application it's impossible to give more concrete guidance, but perhaps you have a situation where not all controls are in use at the same time, but rather that there is some sort of paging. If that is the case, each "page" could perhaps be made into a user control, so that you can load and unload pages as they are needed.
A better idea would be to split your UI up using a TabControl. It has lazy loading built in.
Per MSDN :
Controls contained in a TabPage are not created until the tab page is shown, and any
data bindings in these controls are not activated until the tab page is shown.
And that design is directly aimed at your problem.
Performance isn't your only problem. There are OS limits on the number of handles a process can own, and there are limits on the nested control layout WinForms will perform. If you have 200+ Windows Forms controls on a single window, I'm betting you're going to run into these and other limits.
I recommend changing your Form so that there are fewer controls: paging, virtualization, lazy loading are some techniques you can use to improve your UI and your performance.
Things to try that others haven't mentioned:
Take the [DebuggerStepThru] option off of InitializeComponent, then you may see which items are taking long more easily (w/ profiler or just randomly hitting 'pause' in the IDE during load 20x and remembering where it stops most).
Convert to WPF if your boss will let you.
Take the forms InitializeComponent's items, outof initialize component and on clipboard. Add a timer w/ 20MS ticks. On tick, increment a counter. Add one control per tick, by splitting your initializecomponent code into a 200-case select statement. At 201 stop the timer. That way the user can start working before all the controls are added. You will have to rearrange the controls.add so they show up. You will have to show the important controls first. You will not be able to modify your form in the designer. Lastely, I pity the foo who thinks this bullet point is anything but a joke.
I believe NGen-ing your application can help the performance a lot. Most of those controls (some of them possibly custom in your application) need to be NGen-ed and that usually takes a long time, as going back to the same form is always much faster.
While I might agree with Judah, I have seen plenty of forms in an MDI WinForms app that far exceeded 200 total controls logically contained in a form, and the form needed every one of them to do its job. An invoice entry window for instance would have a set of controls for a header, then a set of user controls that each mapped to an invoice line and had fields for SKU, description, quantity, unit price, extended price, unit tax, etc. Such a window's control count depends on the number of invoice lines, and a large order can generate an invoice requiring thousands of controls to be bound and rendered on a single screen if done naively. Add in further per-line detail for shipping instructions, tax information, backorder status etc. and attempting to pre-load and render every control on window load would crash the application.
7 seconds seems excessive, though. I agree with Frederik; the first step is to look and see if all 200 controls have to be rendered in order to show a single screen's worth of information. Using tab controls, with event handlers for tab changes that "lazy-load" the information and controls shown on each tab, is a good first step. If you show lines of repetitive child information (like invoice lines on the invoice) you can save time by loading a finite page of information at a time; loading 10 lines is far cheaper than loading 100, and while there is some overhead in talking to a DB and dynamically loading controls that will be repeated more often this way, it will seem trivial compared to waiting several seconds just to see ANYTHING load on the window.
I am working on a WinForms project which feels sluggish. It is composed of a literally hundreds of User Controls. If there is a piece of a UI functionality (even if not used anywhere else in the app), it's encapsulated in a User Control. I've gone through the project a number of times with the ANTS profiler and most of the heavy code appears to be in various control constructors.
Before I start ripping out User Controls, do they represent significant overhead to a WinForms application versus just laying out the form without User Controls (e.g. just intrinsic controls)?
A user control is a container for other controls. Having hundreds of them probably means you have multiple hundreds of windows in your project. A window is a very expensive operating system object. They start to noticeably drag down painting perf when you have more than 50 or so.
The comparison to Outlook is apt. That's a good sized chunk of a program. It has less than 50 windows. Easy to see with Spy++.
The difference is OnPaint. Microsoft wrote a lot of code, they didn't drop a lot of controls on a form.
I've been in User Control hell and it's not fun. A few things I've noticed:
If you have too many user controls and move your form around or scroll, you can wind up with a lot of white flickering as the drawing operations of deeply nested window handles fight for rendering time. This is particularly noticeable when you first open up the form.
Beware of nested user controls in the designer. If you open a user control in the designer, the constructor won't be called (it actually generates the designer surface by parsing the compiler-generated code.) However, user controls used by that user control will have their constructors called. This is usually not a problem, but it's worth knowing about if you see odd things happening.
If you have a large solution with lots of user controls, VS 2008 will take a long time to enumerate all of your projects to find all possible controls the first time you open the designer pane. This is a relatively minor annoyance, but it can consume time.
That said, User Controls are definitely handy and worth using in moderation. The main thing I try to avoid is overly deep nesting. I've found that WPF is much better in this respect. It has full control over the rendering pipeline, so you don't get the repainting issues associated with deep composition of controls.