By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,652 Members | 1,473 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,652 IT Pros & Developers. It's quick & easy.

Windows Forms apps not "ending" when you close the form window

P: n/a
Hi,
I've been having a problem with C++ Windows Forms apps not "ending"
when you close the form window. I've searched about this problem all
over the place and most searches have lead me to believe that this has
to do with unreleased form component events or event handlers.

I'm comparatively new to .net and windows forms, in the sense that
though I've been using them for over 2 years now, it's been rather
sporadic. I work with computer-machine interfaces quite a bit, so I'm
mainly doing ANSI C++/STL so stuff can run on whatever OS the
implementer chooses, and the input is usually handled by an external
component that's hooked up to this code. Lately though, more and more
instances have risen where a proper user interface was needed, and
Windows Forms has been brilliant in providing an unbelievably fast
development process for even multi-form, parsed-input,
validation-requiring apps. That is, until I decided to get some of the
information processing code inside the app itself...

Up until now, I've been creating the input forms, which would then
(after the information was submitted) send this information elsewhere
to be processed. Sometimes this required some additional processing by
another program, and sometimes it just hooked up directly to the
interface which connected to the external element, often some sort of
embedded devide that would cache the data while feeding it to whatever
mechanism was using it.

Now, however, I've been presented with a situation where I know that
the client will be using windows-only, and connecting the computer
directly to the device, whichout buffering. So I thought I'd try
simplifying things for everyone and just place everything inside one
C++.net app. This, apparently, held some inherent issues I had no idea
about. Previously, the Forms apps I've created just took the data, did
very mild parsing, and output some XML file to be picked up by another
program. Now, the data needs to undergo mathematical manipulation, sent
back to the form to be displayed as a graph, and only then sent out to
the output element. I haven't even reached the output stage, and it's
already at a point where most of the time, running the program, working
with it a bit, and closing it, will not end the process. In debug mode,
the form just goes away, but the debugging goes on because the process
is still active.

To clarify, my background is rather "que-centric". Instructions stand
in line, get processed, and then the que moves ahead. This is how my
mind works because I've been doing mostly single-threaded C++/STL for
larger scale systems, and C/asm for embedded stuff. All pointer-related
stuff is placed in containers, and so are arrays. If it's embedded, use
macros to make sure that you don't leave "things hanging". This may
seem stone-age for windows programmers, but really, even with the
latest PicMicro dsPics, you don't usually thread. Thus, the whole
notion that you have a person running, throwing a ball up in the air,
keep running, and catching the ball when it falls so as to see what
stuck to it, is very new to me. Moreover, if I have this right, this
isn't really threading, or is it? Does it have to do with the managed
heap?

I should also mention that the app doesn't really "need" the user to do
anything in order to remain an open process when the form closes.
Sometimes I run it, and close it almost right away, and it still
remains active. I've narrowed down the controls so now there are only
one button, one trackbar, and a panel on which the graph is placed on.
It's the minimum required elements to have the mathmatical process be
called and then sent back.

So basically, any general information about the subject would be
useful. I suppose some means of tracking when something has been
removed from the managed heap would help, although I do delete every
gcnew object I create when I'm done with it (does that dispose of it?
Is there anything else that I should be doing/checking?). But then, if
this is a "floating even" problem, I don't even know how to access this
data... I mean, what *is* an unhandled event? An instruction waiting to
be finalized? How do I trace something like that?

Thanks in advance for any info or pointers,
-Moran

Sep 12 '06 #1
Share this Question
Share on Google+
10 Replies


P: n/a

<mo********@gmail.comwrote in message
news:11**********************@d34g2000cwd.googlegr oups.com...
Hi,
I've been having a problem with C++ Windows Forms apps not "ending"
when you close the form window. I've searched about this problem all
over the place and most searches have lead me to believe that this has
to do with unreleased form component events or event handlers.
Did you pass the Form to Application.Run?

Can you just use the Closed event of the Form to call Application.Exit?
Sep 12 '06 #2

P: n/a

Ben Voigt wrote:
<mo********@gmail.comwrote in message
news:11**********************@d34g2000cwd.googlegr oups.com...
Hi,
I've been having a problem with C++ Windows Forms apps not "ending"
when you close the form window. I've searched about this problem all
over the place and most searches have lead me to believe that this has
to do with unreleased form component events or event handlers.

Did you pass the Form to Application.Run?

Can you just use the Closed event of the Form to call Application.Exit?


The form is called from main():
Application::Run(gcnew Form1());

This is done by the project builder, I didn't tamper with it. When I
close the app, I mean I use the usual close window button on the
top-right. I've also tried calling this->Close() from within the form,
and Application::Exit(), both yielding the same result -- the form
closes, but the app, 80% of the time, doesn't. Actually I should
probably say that the form closes visually, since I'm guessing that
considering there's nothing after it within main(), apart from return
0, that the form is actually still running, I just can't see it...

Any ideas?

Sep 13 '06 #3

P: n/a
Any ideas?
Break into debugger and check call stacks of all threads.
What is the main thread doing? What are other threads doing?
It might give you an idea of what is going on.

Regards,
Oleg
[VC++ MVP http://www.debuginfo.com/]

Sep 13 '06 #4

P: n/a
Oleg Starodumov wrote:
Any ideas?

Break into debugger and check call stacks of all threads.
What is the main thread doing? What are other threads doing?
It might give you an idea of what is going on.

Regards,
Oleg
[VC++ MVP http://www.debuginfo.com/]


I haven't dug into the debugger enough, and I will. I'm used to
internal logging and exceptions every now and then for debugging, but
obviously it won't be enough this time.

Your message did give me an idea about something I hadn't considered
using yet, the Spy++ tool, and it had some very odd results. When the
program is running, it shows 4 threads. When the form is closed, using
any method, including application::exit(), the amount of threads jumps
to 7! Out of those, 5 are just addresses, while 2 of them show familiar
components:

thread:
Window (hex) .NET-BroadcastEventWindow.2.0.0.0......
Window (hex) "M" MSCTFIME UI
Window (hex) "Default IME" IME

thread:
Window (hex) "GDI+ Window" GDI+ Hook Window Class
Window (hex) "Default IME" IME

The second thread exists as-is when the program is running, prior to
being closed. The first is part of a thread which also contains all of
the form controls, literally by-name, again, when the program is
running.

So basically, when there's an attempt to close the app, 3 "nameless"
threads appead, and the form controls are removed from 2 of the
existing threads.

Is it the "BroadcastEventWindow" that's preventing the app from
closing? I should also mention that when in debug mode, there's no
problem ending the process by clicking "terminate all" instead of
"close", though I'm guessing that this is obvious to anyone who uses
the debugger on any regular basis.

I can only deduce from this that the form, and/or the app if attempting
to close things in an orderly manner, handling events along the way
like ApplicationExit, and something is preventing this process from
reaching its goal. I suppose that I can also, possibly, deduce that if
the controls are removed from the thread after the form is closed, even
if the app doesn't shut down, that each of these control's events have
also been handled and closed, but then why would there suddenly be
additional threads?

I don't know enough to learn anything more from this information...
I'll go look into the debugger documentation in the meantime and see
what I can glean that way.

Thanks for the replies. If anyone knows how to interpret the thread
info above, or has any ideas on the matter, it'd really help.

Thanks,
-Moran

Sep 13 '06 #5

P: n/a
So basically, when there's an attempt to close the app, 3 "nameless"
threads appead, and the form controls are removed from 2 of the
existing threads.
I would suspect that the application starts a worker thread
and does not terminate it properly and/or does not mark it
as background (Thread.IsBackground).
The thread, in turn, prevents the app from finishing.

This could be proved or disproved by looking at the list of threads
and their call stacks with the debugger (offending thread(s) would be visible,
and the main thread would be waiting for them to complete; RPC worker
threads could be started as a side effect (though the latter will not be visible
in the list of threads when debugging in managed or mixed mode)).

Even if my guess is wrong, the call stack of the main thread would give
some insight into what the app is currently doing.
Is it the "BroadcastEventWindow" that's preventing the app from
closing?
Probably not.
I should also mention that when in debug mode, there's no
problem ending the process by clicking "terminate all" instead of
"close", though I'm guessing that this is obvious to anyone who uses
the debugger on any regular basis.
It's good information too, since it tells that the problem is not related
to pending I/O (other possible reason for a failure to terminate properly).

Oleg


Sep 13 '06 #6

P: n/a

Oleg Starodumov wrote:
So basically, when there's an attempt to close the app, 3 "nameless"
threads appead, and the form controls are removed from 2 of the
existing threads.

I would suspect that the application starts a worker thread
and does not terminate it properly and/or does not mark it
as background (Thread.IsBackground).
The thread, in turn, prevents the app from finishing.

This could be proved or disproved by looking at the list of threads
and their call stacks with the debugger (offending thread(s) would be visible,
and the main thread would be waiting for them to complete; RPC worker
threads could be started as a side effect (though the latter will not be visible
in the list of threads when debugging in managed or mixed mode)).

Even if my guess is wrong, the call stack of the main thread would give
some insight into what the app is currently doing.
Is it the "BroadcastEventWindow" that's preventing the app from
closing?

Probably not.
I should also mention that when in debug mode, there's no
problem ending the process by clicking "terminate all" instead of
"close", though I'm guessing that this is obvious to anyone who uses
the debugger on any regular basis.

It's good information too, since it tells that the problem is not related
to pending I/O (other possible reason for a failure to terminate properly).

Oleg



I've been breaking into the debugger at all sorts of places, and I
can't find a location which provides useful information because it's
one of two contingencies: Either it's breaking before the closing
function (whichever one it may be) is called, in which case I see what
I'd expect to see at that point, or it's managed to pass the closing
function and it's breaking, basically, right before "return 0". If the
form actually does "hang" without closing, it's hanging between the two
break points, and the stack and thread tables are empty... How do I get
the information about what's open at that particular moment, where the
app is still running, but it's within a sealed function?

Also, I've noticed the probability of a hang climbs as more system
resources are being used in the background, something I haven't noticed
until now. Since I had around 20 browser windows/tabs opened with all
sorts of references about the debugger and the managed heap, I was
bogging down the system and increasing the chances of this occurring.
After X amount of crashes on the side of other apps, which didn't like
the load on the system either, I restarted, and suddenly found that it
only froze around 20% of the time. Now I use a simple method to get it
to freeze: I play some video file in the background then I close the
app, making sure that system resources are being stressed. If the CPU
usage is high enough, it almost never closes. I'm sure this is
indicative of something, I just wish I knew what... It doesn't take
much to get it to freeze up though, just a few browser windows will
push it over 50%.

Thanks a lot for the help so far. At the very least I'm gradually
learning where to look in order to track these things down, even if not
effectively. If there's a way to break into the debugger info tables at
an arbitrary point (with my luck there probably is, and it's probably
in plain sight, I just can't find it...), that'd help a lot.

Thanks again,
-Moran

Sep 13 '06 #7

P: n/a
I've been breaking into the debugger at all sorts of places, and I
can't find a location which provides useful information because it's
one of two contingencies: Either it's breaking before the closing
function (whichever one it may be) is called, in which case I see what
I'd expect to see at that point, or it's managed to pass the closing
function and it's breaking, basically, right before "return 0". If the
form actually does "hang" without closing, it's hanging between the two
break points, and the stack and thread tables are empty... How do I get
the information about what's open at that particular moment, where the
app is still running, but it's within a sealed function?
Have you tried Debug | Break All? (at the moment when the application
cannot close)

Oleg

Sep 14 '06 #8

P: n/a

Oleg Starodumov wrote:
I've been breaking into the debugger at all sorts of places, and I
can't find a location which provides useful information because it's
one of two contingencies: Either it's breaking before the closing
function (whichever one it may be) is called, in which case I see what
I'd expect to see at that point, or it's managed to pass the closing
function and it's breaking, basically, right before "return 0". If the
form actually does "hang" without closing, it's hanging between the two
break points, and the stack and thread tables are empty... How do I get
the information about what's open at that particular moment, where the
app is still running, but it's within a sealed function?

Have you tried Debug | Break All? (at the moment when the application
cannot close)

Oleg


Yes! I forgot to mention that, because it wasn't really fruitful...

If the "Just My Code" option is disabled, it won't allow me to break at
that point, saying: "No symbols are loaded for any call stack frame.
The source code cannot be displayed.". If it's enabled, the stack is
empty, and it shows 2 threads running, with no real info:

= 4944 <No Name> Normal 0
5176 <No Name> Highest 0

Also, if it's of any use at all, here are the modules running at that
point (where there's no form but the app is still running):

mscorlib.dll /Yes /No /Skipped loading symbols. /1
intvecs.exe: Managed /No /Yes /Symbols loaded. /2
msvcm80d.dll /No /Yes /Symbols loaded. /3
System.dll /Yes /No /Skipped loading symbols. /4
System.Windows.Forms.dll /Yes /No /Skipped loading symbols. /5
System.Drawing.dll /Yes /No /Skipped loading symbols. /6

Just by trying to pick at things and throw them back, it seems to be
something related to either a Graphics object, or a GraphicsPath
object. But there's just one of each, and I don't know what else to do
but call delete when I'm done with them. I do pass the GraphicsPath
handle to one function, but that shouldn't change anything, I think.
Apart from that, there's also an "array<PointF>^" that is created and
deleted in the same block. If I do an inventory of the rest of the
gcnew created objects, you can guess there's also a pen and a brush.
That's it, there isn't anything else I manually created on the managed
heap, there's just the form controls made by the form designer.

I'm starting to lean back to the old method of throwing the raw data
out to a non-form program and have it send it back. It's a really
backward way of doing things but it works. The real irony here is that
I've created extremely overdone forms in the past, with runtime control
creation, runtime graphics changes and modifications, list controls
being created on the fly and populated with info that's sorted in
real-time, overlapping graphs, dragging elements, and those things just
worked. I've never had this happen before. Really odd.

-Moran

Sep 14 '06 #9

P: n/a
If the "Just My Code" option is disabled, it won't allow me to break at
that point, saying: "No symbols are loaded for any call stack frame.
The source code cannot be displayed.". If it's enabled, the stack is
empty, and it shows 2 threads running, with no real info:

= 4944 <No NameNormal 0
5176 <No NameHighest 0

Also, if it's of any use at all, here are the modules running at that
point (where there's no form but the app is still running):

mscorlib.dll /Yes /No /Skipped loading symbols. /1
intvecs.exe: Managed /No /Yes /Symbols loaded. /2
msvcm80d.dll /No /Yes /Symbols loaded. /3
System.dll /Yes /No /Skipped loading symbols. /4
System.Windows.Forms.dll /Yes /No /Skipped loading symbols. /5
System.Drawing.dll /Yes /No /Skipped loading symbols. /6
It looks like the debugger works in managed only mode,
and all threads are currently in native code. Try to enable mixed mode,
or native mode (try both and see which one will give the best results).
The debugger mode can be set in Project properties | Configuration properties |
Debugging | Debugger type (use either "mixed" or "native", but not "auto" or "managed")

Also disable Just My Code.

Oleg


Sep 15 '06 #10

P: n/a
Oleg Starodumov wrote:
If the "Just My Code" option is disabled, it won't allow me to break at
that point, saying: "No symbols are loaded for any call stack frame.
The source code cannot be displayed.". If it's enabled, the stack is
empty, and it shows 2 threads running, with no real info:

= 4944 <No NameNormal 0
5176 <No NameHighest 0

Also, if it's of any use at all, here are the modules running at that
point (where there's no form but the app is still running):

mscorlib.dll /Yes /No /Skipped loading symbols. /1
intvecs.exe: Managed /No /Yes /Symbols loaded. /2
msvcm80d.dll /No /Yes /Symbols loaded. /3
System.dll /Yes /No /Skipped loading symbols. /4
System.Windows.Forms.dll /Yes /No /Skipped loading symbols. /5
System.Drawing.dll /Yes /No /Skipped loading symbols. /6

It looks like the debugger works in managed only mode,
and all threads are currently in native code. Try to enable mixed mode,
or native mode (try both and see which one will give the best results).
The debugger mode can be set in Project properties | Configuration properties |
Debugging | Debugger type (use either "mixed" or "native", but not "auto" or "managed")

Also disable Just My Code.

Oleg


Hi again,
I should have updated more frequently, but mainly I was digging around
for information about what types of elements were "conjured" when a
windows forms app was launched, as well as how events were handled, and
how to use the debugger in a more than a guessing-game manner.

Your pointers were really great, they saved me a lot of time looking
for the right keywords and checking for what to look for in the project
properties and configuration properties. I had previously not touched
these at all, and just treated the .net portion of the code as a
black-box into which I'd bridge code.

I've received a bunch of insightful E-mails with very insightful
exercises:

Step 1) There's no need for any external code to be called -- at all.
Just load a windows forms app that happens to have a bunch of code
compiled into it (which does nothing at all -- it isn't even called
once).

Step 2) Place a few controls around the form, and set onclick events to
some of them. Trackbars are very good at this.

Step 3) Run something in the background that gets your CPU usage to
over ~40%. Video's good because it's consistent.

Step 4) Just run the app and close it a few times. Now this really
depends on your system and the processes working in the background, but
you'll get "frozen" threads starting to pile up pretty soon.

Step 4b) Run the app and close it as soon as you can, possibly don't
even give it a chance to finish loading all the controls. This almost
guarantees a frozen thread.

Once you've done these things, go to the task manager and close all the
threads manually. Now restart your computer. You'll get a process
message which awaits manual closing called something along the lines of
".Net Broadcastwindow". This, as it turns out, is quite a broad
subject. If you google it, you'll see it pops up in driver issues, in
various software updates, and a whole bunch of .Net dev sites, but I've
yet to find something with proper instructions on how to solve the
problem, or how it connects to the frozen threads. Apparently it does,
though, since for the first time I'm seeing problems similar to the
ones I'm experiencing.

I'll keep searching along this path, but it strikes me as extremely odd
that it's so easy to create these "frozen" or "hanging" threads. I'm
almost positive that there's some very simple way around this, since
it's not possible that it's this simple to throw a monkey wrench into a
windows forms app. There has to be some way of isolating the rest of
the code somehow, or setting a "terminate all" trigger on the close
event of the window, although that wouldn't exactly be a very elegant
solution.

Thanks again for all the help,
-Moran

Sep 22 '06 #11

This discussion thread is closed

Replies have been disabled for this discussion.