Jonathan Henson
Jonathan Henson

Reputation: 8206

Windows Forms app slows down after about 12 hours

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.

Upvotes: 1

Views: 2383

Answers (1)

Jodrell
Jodrell

Reputation: 35696

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.

Upvotes: 2

Related Questions