I am working on a large scale project where a custom (pretty good and robust) framework has been provided and we have to use that for showing up forms and views.
There is abstract class StrategyEditor (derived from some class in framework) which is instantiated whenever a new StrategyForm is opened.
StrategyForm (a customized window frame) contains StrategyEditor.
StrategyEditor contains StrategyTab.
StrategyTab contains StrategyCanvas.
This is a small portion of the big classes to clarify that there are many objects that will be created if one StrategyForm object is allocated in memory at run-time. My component owns all these classes mentioned above except StrategyForm whose code is not in my control.
Now, at run-time, user opens up many strategy objects (which trigger creation of new StrategyForm object.) After creating approx. 44 strategy objects, we see that the USER OBJECT HANDLES (I'll use UOH from here onwards) created by the application reaches to about 20k+, while in registry the default amount for handles is 10k. Read more about User Objects here. Testing on different machines made it clear that the number of strategy objects opened is different for message to pop-up - on one m/c if it is 44, then it can be 40 on another.
When we see the message pop-up, it means that the application is going to respond slowly. It gets worse with few more objects and then creation of window frames and subsequent objects fail.
We first thought that it was not-enough-memory issue. But then reading more about new in C# helped in understanding that an exception would be thrown if app ran out of memory. This is not a memory issue then, I feel (task manager also showed 1.5GB+ available memory.)
M/C specs
Core 2 Duo 2GHz+
4GB RAM
80GB+ free disk space for page file
Virtual Memory set: 4000 - 6000
My questions
Q1. Does this look like a memory issue and I am wrong that it is not?
Q2. Does this point to exhaustion of free UOHs (as I'm thinking) and which is resulting in failure of creation of window handles?
Q3. How can we avoid loading up of an StrategyEditor object (beyond a threshold, keeping an eye on the current usage of UOHs)? (we already know how to fetch number of UOHs in use, so don't go there.) Keep in mind that the call to new StrategyForm() is outside the control of my component.
Q4. I am bit confused - what are Handles to user objects exactly? Is MSDN talking about any object that we create or only some specific objects like window handles, cursor handles, icon handles?
Q5. What exactly causes to use up a UOH? (almost same as Q4)
I would be really thankful to anyone who can give me some knowledgeable answers. Thanks much! :)
[Update]
Based on Stakx answer, please note that the windows that are being opened, will be closed by the user only. This is kind of MDI app situation where way too many children windows are opened. So, Dispose can not be called whenever we want.
Q1
Sounds like you're trying to create far too many UI controls at the same time. Even if there's memory left, you're running out of handles. See below for a brief, but fairly technical explanation.
Q4
I understand a user object to be any object that is part of the GUI. At least until Windows XP, the Windows UI API resided in USER.DLL (one of the core DLLs making up Windows). Basically, the UI is made up of "windows". All controls, such as buttons, textboxes, checkboxes, are internally the same thing, namely "windows". To create them, you'd call the Win32 API function CreateWindow. That function would then return a handle to the created "window" (UI element, or "user object").
So I assume that a user object handle is a handle as returned by this function. (Winforms is based on the old Win32 API and would therefore use the CreateWindow function.)
Q2
Indeed you cannot create as many UI controls as you want. All those handles retrieved through CreateWindow must at some point be freed. In Winforms, the easiest and safest way to do this is through the use of the using block or by calling Dispose:
using (MyForm form = new MyForm())
{
if (form.ShowDialog() == DialogResult.OK) ...
}
Basically, all System.Windows.Forms.Control can be Disposed, and should be disposed. Sometimes, that's done for you automatically, but you shouldn't rely on it. Always Dispose your UI controls when you no longer need them.
Note on Dispose for modal & modeless forms:
Modal forms (shown with ShowDialog) are not automatically disposed. You have to do that yourself, as demonstrated in the code example above.
Modeless forms (shown with Show) are automatically disposed for you, since you have no control over when it will be closed by the user. No need to explicitly call Dispose!
Q5
Everytime you create a UI object, Winforms internally makes calls to CreateWindow. That's how handles are allocated. And they're not freed until a corresponding call to DestroyWindow is made. In Winforms, that call is triggered through the Dispose method of any System.Windows.Forms.Control. (Note: While I'm farily certain about this, I'm actually guessing a little. I may not be 100% correct. Having a look at Winforms internals using Reflector would reveal the truth.)
Q3
Assuming that your StrategyEditor creates a massive bunch of UI controls, I don't think you can do a lot. If you can't simplify that control (with respect to the number of child controls it creates), then it seems you're stuck in the situation where you are. You simply can't create infinitely many UI controls.
You could, however, keep track of how many StrategyEditors are opened at any one time (increase a counter whenever one is instantiated, and decrease it whenever one is closed -- you can track the latter using the FormClosing/FormClosed event of a form, or in the Dispose method of a control). Then you could limit the number of simultaneously opened StrategyEditors to a fixed number, say 5. If the limit is exceeded, you could throw an exception in the constructor, so that no more instances are created. Of course I can't say whether StrategyForm is going to handle an exception from your StrategyEditor constructor well...
public class StrategyEditor : ...
{
public StrategyEditor()
{
InitializeComponent();
if (numberOfLiveInstances >= maximumAllowedLiveInstances)
throw ...;
// not a nice solution IMHO, but if you've no other choice...
}
}
In either case, limiting the number of instantiated StrategyEditors seems like a temporary fix to me and won't solve the real problem.
Related
I have two separate programs, one is a console application, and the other one is a windows application.
My windows application:
Has a graphic interface, buttons, and others functions.
One of the buttons, named "research": when I click on it, I launch the console application with this line of code:
string strResult = ProcessHelper.LaunchProcessWaitForPipedResult("MyExecFile.exe", strArguments, 10 * 60 * 1000, true); // 10 mins max
My console Application:
do a query on all existing files in a directory.
My problem:
I want to create a progress-bar on the windows application to show the progress of the console application. The problem is I don't know how to pass this information between the two processes. The only restriction is to not use a database or file.
Given two processes in the same user session, and wanting to avoid any communication outside that session I would look at three options:
1. Using named pipes.
The parent process creates a named pipe using a random name (and confirms that name is not in use by opening it). It passes that name to the child process. A simple protocol is used that allows the child to send updates.
There are a number of challenges to overcome:
Getting the logic to ensure the name is unique right (named pipe names are global).
Ensuring no other process can connect (the default named pipe ACL limits connections to the session: this might be enough).
Handling the case where a different parent process does not support progress updates.
Handling the child or parent crashing.
Avoiding getting too clever with the communication protocol, but allowing room for growth (what happens when more than a simple progress bar is wanted?)
2. Using Shared Memory
In this case names of objects are, by default, local to the session. By default this is more secure.
The parent process creates a sufficiently large amount of shared memory (for a simple progress update: not much), a mutex and an event.
The parent process then, concurrently with the GUI waits for the event to be signalled, when it is it enters the mutex and reads the content of shared memory. It then unsets the event and leaves the mutex.
Meanwhile to send an update the child enters the mutex, updates and memory and sets the event before leaving the mutex.
The challenges here include:
Defining the layout of the shared memory. Without a shared assembly this is likely to be error prone.
Avoiding others using the shared memory and synchronisation objects. .NET makes things harder here: in Win32 I would make the handles inheritable thus not needing to name the objects (except for debugging) and pass to the child directly.
Getting the sequencing of shared memory, mutex and event correct is critical. Memory corruption and more subtle bugs await any errors.
It is harder to do variable length data with shared memory, not an issue for a simple progress count but customers always want more.
Summary
I would probably look at named pipes in the first place (or perhaps custom WMI types if I wanted greater flexibility). BUT I would do that only after trying everything to avoid needing multiple processes in the first place. A shared library plus console wrapper for others, while I use the library directly would be a far easier option.
This is a follow up question to this answer https://stackoverflow.com/a/20584601/2530848.
I was under the impression that Control class doesn't implement finailzer which is true indeed, so leaked controls are leaked forever, not cleaned up during finalization.
Hans Passant gives some hint in comments section saying that it does, and some keyword ParkingWindow. I googled with that keyword, can't find any helpful resource about that.
Finally I found a class named ParkingWindow in System.Windows.Forms.Application.ParkingWindow through decompiler, I can't get to understand what is being done with that.
It looks like unparented windows will be parented to this parkingwindow and destroyed later at some point but not sure.
Question is what exactly is ParkingWindow and What it is used for?
Edit: How that is related to Control's Finalization or cleanup?
and destroyed later at some point but not sure
That "not sure" is the crux of the problem. This goes wrong very often with the window not getting destroyed at all.
Shawn Farka's blog post explains the original intent of the Parking Window well. The expense of having to re-create the child windows was certainly on top of the list. Not the only concern though, some types of child windows are very difficult to re-create accurately. A TreeView is a good example, there's rather a lot of runtime state associate with it. To do it accurately, you'd have to record the collapse state of every node. That's painful and Winforms does not in fact do this. When you re-assign, say, the CheckBoxes or StateImageList properties then you'll see this going wrong.
All and all, it is a nice trick but they went overboard with it. A child control doesn't just (temporarily) end up on the Parking Window when the parent window gets recreated, it also is moved there when:
you set its Parent property to null
you use the parent's Controls collection's Remove/At() method
you use the parent's Controls collection's Clear() method
Particularly the last two bullets are almost always deadly in a typical Winforms program. They tend to be used when the programmer dynamically adds and removes controls at runtime. Problem is, the control is re-hosted on the Parking Window but the programmer just forgets them there, losing the reference to the control. And they will live there forever. Until the user terminates the program because it turns into slow molasses from having thousands of windows created. Or the program crashes with "Error creating window handle". Which occurs when Windows gets sulky after the program has created 10,000 windows.
Instead, it is required to call the Dispose() method of the control. Very unusual in .NET in general, calling Dispose() is always optional. Not in the case of the Control class, the Parking Window keeps a reference on the control and thus prevents the finalizer from running.
This is covered on this article by Shawn Burke from MS: Windows Forms Parking Window.
One of our goals with Windows Forms was try to smooth out as much of
the oddity of Win32 as we could. And one of the principal oddities is
that of window handle (HWND) management and lifetime. We certainly
didn't want the average user to need to worry about this stuff. In
most cases, it was pretty easy. You just gather up all of the state,
and then when you actually need to show the window, you do the
creation on demand, then you drive your state off the HWND instead of
your internal members.
Well, this doesn't always work so well. See, there are certain
properties of Win32 windows that you can't change once the window is
created. Like the style of the border, for example. So to allow a
user to change the border style after the window has been created, you
need to recreate the handle. Which means you need to not only pull
all of the state out you want out of the existing one, but you need to
recreate it and push it back in. Okay, that's not too hard.
But what about the children? Oh, fiddlesticks. The kids.
If the window you're modifying the border on has children, destroying
its handle will destroy the handles of all of its children as well.
Then you need to recreate them, which is very expensive. And
expensive is bad.
Enter the Parking Window. The Parking Window was our solution to this
problem. It was somewhere that you could "park" HWNDs until you have
a fitting parent for them. Think of it as Window Handle Foster Care,
but invisible.
So in the case of a handle-recreate, we'd check to see if there were
any children. If there were, we'd (if needed) create the Parking
Window, parent the children to that, recreate the parent's handle,
then move them back over. Worked pretty well, though managing the
lifetime of the Parking Window did cause some problems...
I was considering using a Singleton pattern in a winforms application that I am working on, but a lot of people seem to think that singletons are evil. I was planning on making a "Main Menu" form which is a singleton. I can't think of any reason that I would want multiple instances of my Main Menu, and it is always going to be the first form that comes up, so I am not concerned with wasting resources if it gets instantiated unnecessarily.
Also, I could see issues arising if there are multiple instances of the Main Menu. For example, if another form has a "Main Menu" button and there are multiple instances of the Main Menu, then the decision of which instance to show seems ambiguous.
Also, if I have another winform which has to look at the state of the program to determine whether there is already an instance of the main menu, then I feel like I am breaking modularity, though I might be wrong.
Should I be avoiding the use of a singleton in this case or would it be better to make the Main Menu static?
I just started using c# a couple days ago, and I haven't really done much with OOP in the last few years, so I apologize if this is a stupid question.
Thanks
Is MainMenu shown all the time? If not, it would make sense to release the old instance when it's closed and create a new one every time you need to open it. This way other modules won't need to know of its instances, they'll just create one when they need to open it.
People like global state. It is apparently easy to understand, and makes sense to us. You don't have to worry about which version you are using because they are all the same.
However global state introduces all kinds of odd errors, so is generally discouraged. C# made many design decisions to make global state harder to miss use. For instance you are allowed static variables only attached to a class that must manage them.
Singletons are another way to get this global state, however they are similar in that they can cause issues. What if one of your screens sets a part of the main menu then transitions to it, not realizing that a background process undid the change, resulting in an odd main menu being displayed?
The other alternative to singletons is to ensure that the variables reach where they are needed. One way of doing that is to keep track of a stack of menus, in fact Android works like this underneath. Every UI gets a set of parents that are above it, that it can switch to if it wants to go back. By ensuring that only your initial boot up process creates the initial main menu screen, you can guarantee only one is created, however all screens can still access it by checking the hierarchy.
Additionally if you are talking about winforms, they already have a hierarchy system built in that you can use to provide this functionality.
You can abuse almost everything.
A singleton is a way to guarantee that there is only one instance of an object active at any time, and you can synchronize access to it. With a static class you lose that, since the static class can be accessed by anyone at any time, you need to make sure your methods don't do nothing that can be affected by concurrency.
Beyond that, if i'm reading you right, you want a form that would be the parent form to have the only instance of your menu and all other form would be childs of this one. If this is the case then you should check MDI (Multiple Document Interface) in Winforms since this will cover your scenario just right.
Otherwise, what i would do, is simply to define a class for my parent form (the one with the main menu) and have a singleton expose accest to it, and use another base class for all the child forms.
I have a UI, winform, It has loads of controls like tabcontrols, Plenty of text boxes(min 25 spread across tabs) comboxes, checkboxes, buttons, labels, tree control etc.
most of these controls register for ctrl events like textchanged, click etc...
Since i am getting this out of memory exception and all i have few queries:
Questions:
In the dispose function of the form should dispose of each of this ctrl be called ?
Should the events subscibed by the ctrls like the textchanged, click event etc be de-registered in the dispose function ? Does the GC take care of de registering the events added for the ctrls, as the code snippets are added in the designer?
Some Info:
The application was put on a stability test for upto 100 iterations on a 2GB ram machine. Each iteration it would execute the same test(launching teh dialog, doing some clicks or editing some values, and closing). It was on running for almost 8 hrs. on the 45 th or the 46 th iteration it threw this exception. Yes all the controls in the dialog have one event or ther other registered. some text changed some checkedchanged or click etc
I don't think there's enough information here to tell you exactly what's going on. This will take some careful analysis of the code on your part, but the first thing to do is to run your app through a memory profiler. For example, ANTS Memory Profiler, but really anything you have access to will do fine) to see what's really going on.
Normally, you wouldn't need to explicitly dispose of every control, but if you're subscribing to events, that can cause things to hang around in memory longer than usual. This question has the gory details, but in a nutshell, you want to unsubscribe or use weak references to fix that; no need to enumerate all form controls and call Dispose. If I recall, it should be called on Form.Close() anyway, unless it's an MDI form and it's not visible when Close is called.
You should also look at what data you're storing and how, as well as whether or not you're properly disposing of whatever resources your application may be using.
If you're running on a 32-bit system, you might also be running against the per-process memory limit of 2GB, which you can hit if you, say, keep a List around that grows to 1GB and has to resize.
So, arm yourself with a profiler and get investigating. :)
A Programmer in my office has written an incredibly large application in Windows Forms. Anyways, he keeps having trouble with the application slowing down after about 12 hours. We have confirmed that it is the actual Event Loop that ends up running slowly and not the code after the events fire. For instance, even typing into a textbox will be extremely slow. He has several socket communication threads, which we have confirmed are running at normal speed. The only thing I can think of is that he has several System.Timers.Timer instances throughout the application. Could they be the problem? The program slows down usually after no one has been using it for about 5 or 6 hours.
I know there could be a long list of possible issues. We just need some advice on where to start looking. I have tried all of the obvious.
One other thing to mention. His architecture consists of a base form, which includes a panel with controls that every page has along with 3 timers, and all other forms inherit from this base form. There are probably 15 or so of these forms, all of which are loaded into memory at startup. We did this, because the client was complaining about switching between the forms the first time took a few seconds. Each form has potentially fifty to one hundred instances of a control we wrote for him to use which does all of his back-end work. There is a static timer in this control and one static thread as well--since there is only one instance regardless of how many instances of the control are in memory, I can't imagine that those are the issue. Also the base form's timers are static.
I cannot vouch for the efficiency of his code, but it does run really well at our office, and for 5 to 6 hours on site.
Any ideas?
Edit:
I just talked to the guy on site and he asked. 1st, the event handler for one of the static timers is not static--how that it is possible for a static timer to access an instance method seems weird to me. Second, the timers' AutoReset is set to true.
Update:
Ok, I finally got with the guy today to look at some of the code.
He had several static members of his class, i.e. the timers, some buttons, and user controls. Then in the constructor he was using the new operator on each of those static members without a static bool isInit flag.
In other words, the static members were being initialized each time a new form was created but only the last one initialized was being referenced. However, I would imagine that the Form Container was holding references to the old objects so the old objects would never get deleted. Also, wouldn't this be bad aliasing for the containers if the object were to be deleted when the static member's reference was changed? Either way, a bad leak, or a bad alias would cause problems. I am hoping that is the only problem. I am having him fix all of that and then we will test again.
To add insult to injury, he was calling GC.KeepAlive(the static timer) that had a new reference inside the constructor. So, he had 21 timers running.
Are you disposing? Are you holding objects in memory? Are you holding on to some other unmanaged resource.
Leave it running, wait till it gets slow, attach a debugger, step through and see which lines are slow in your problem area.
EDIT:
If it only goes slow on site then, if the product is for a specific client you should construct a reference environment that matches the clients as closely as possible. This would be both useful for the future, and useful now for identifying the differences between your systems which are likely the cause of the problem.
I did have a similar sounding issue where we performed some remoting over sockets on background threads between several services on different machines. Unfortunately I can't remember the exact details (sigh.) As I recall we kept requesting at a set time interval but, the reponse time from the service got slower over time, eventually the response time exceded the set interval. This was fine for the first 1000 or so calls, .Net kept a nice growing stack of the callbacks we were expecting. However, eventually this list reached some internal limit and the message pump froze, including all the painting on client GUIs. This was resolved by ensuring that we would not call until we had had a response. This kind of race condition may or may not be what you are experiencing but I thought it may be worth mentioning.