close application causes program to crash and comes up with ms error msg box

rlee923

Newcomer
Joined
Aug 26, 2008
Messages
5
Hi,

I am quite new to .net programming, and I am currently programming something that uses windows forms + mysql to maintain something.

When I call Application.Exit() on a certain form , the program exits

but it crashes and comes up with microsoft error message box.

And the details say that it has semaphorefull.

I have tried to catch the exception and do nothing to handle it so it doesn't come up with error message but its not working.


The basic setup of the the program is that I have a mainform, and there is a button which opens up the other form.

this is the code to bring the new form :

C#:
private void btnAccounts_Click(object sender, EventArgs e)
        {
            frmManageAccounts manageAccountsForm = new frmManageAccounts(username, 
                   dbName, dbHost, password, dbType, dbInstance, permission);
            this.Hide();
            manageAccountsForm.Show();
            
            
            conn.Close();
            cmd = null;

            this.Close();
            this.Dispose();
            GC.Collect();



        }

And this is the exit event handler method
C#:
   private void btnExit_Click(object sender, EventArgs e)
        {
            try
            {

                System.Windows.Forms.DialogResult result =
                    MessageBox.Show("Are you sure to exit?", "Closing Application",
                        MessageBoxButtons.OKCancel,
                        MessageBoxIcon.Exclamation,
                        MessageBoxDefaultButton.Button2);

                if (result == System.Windows.Forms.DialogResult.OK)
                {
                    closeFlag = true;
                    
                    Application.Exit();
                    
                   
                    
                }
            }
            catch (Exception btnExit_Click_E)
            {
                MessageBox.Show(btnExit_Click_E.StackTrace);
            }

           
        }
As you can see there is nothing special and I use the same code on the main form, which works fine on it.

Can you help me with this problem?

Thanks a lot in advance.

Regards,

JH
 
Last edited by a moderator:
I personally would avoid calling Application.Exit as it doesn't call the Finalizers of any instantiated objects - this can cause problems if the clean up code is required. If you close / Dispose of all objects when you have finished with them then closing the main form should exit the application.

Equally calling GC.Collect is a bad idea - if you are closing / disposing of all objects that require explicit management then the GC should handle the rest by itself. In fact calling GC.Collect can cause objects to stay in memory longer than not calling GC.collect!

Could you post the entire error message - or at least any modules it references as this could indicate where the problem lies. I would also check what version of the MySql driver you are using and if there are known issues with it - the fact you are getting an error relating to a semaphore indicates a threading issue and as your code isn't doing any explicit threading then the db driver is a prime candidate.
 
Thanks a lot for the suggestion.

As far as I remember I could not find the specified line of the code. But I will have look again.

I don't think it's mysql driver problem. Because the main form uses mysql connection as well, but it exits fine.

Anyway I am so excited to try the things that you have mentioned. Can't wait to get home and try!.

Thanks a lot for the reply PlausiblyDamp~!.
 
Ok.. now first things first.

I've tried without GC.Collect() and it just builds up mem usage.

For some reason it does not work with just dispose()

Secondly, you might be right about mysql, i am not sure whether it's an error but what happens is if I try to close the connection and exit application, it comes up with an error.

The exact error message is the usual microsoft error and the details in it are:

P9.System.threading.semaphorefull

I will try to figure the relationship between mysql connection and application.exit().

If you have any other suggestion let me know.

Thanks a lot!
 
Ok,... i found a temp solution , which is passing connection itself into constructor and do not close it.

But I found tha tfor some reason, even though nothing is connected, when I launch the login form another thread on the mysql monitor list pops up.
And when I connect, I get two extra, and when I bring up another form, it becomes 4 connections. And when I close the very first one remains.

I wonder whether this is the problem.

Anyway I'll code the program first and think about the problem later.

Should be something very simple I hope!
 
If you have plenty memory then it will be less aggressive in freeing up resources - the GC is designed that way.

Calling GC.collect however can interfere with the collection of objects as it can make short term allocations live longer.
 
Aaaaahh. That's why.

So does it have some kind of threshold ratio of the memory that it starts to do actually clean up? I better read up one GC bit more.

Thanks a lot anyway, I think this issue has been resolve for now.

All the Best!
 
The GC itself is quite sophisticated in how it handles allocations / collections, there isn't a single governing limit that is used...

The benefit of garbage collection is allocations are cheap - it simply grabs more free memory (either already allocated and unused or more from the OS).

Collection on the other hand can be expensive as it also compacts memory so all currently allocated memory is in a contiguous block - this helps to prevent fragmentation i.e. plenty free memory but all of it in small blocks here and there which collectively are big enough to fulfil a request but individually are too small which results in further allocations anyway...

To reduce this overhead on collection .Net uses a generational collection system. When any resource is first allocated it lives in generation 0 - this is always physically allocated after the last currently allocated block of memory. Often variables are short lived (e.g. only last for the duration of a single method or as part of a short lived object) and these are ideal candidates for collection. If the GC deems it necessary to collect then it can attempt to collect and compact just generation 0. Any thing that is no longer needed is freed up while anything that survives is promoted to generation 1.

As long as collection generation 0 frees up enough memory then it will just keep doing so - each object that survives a generation 0 collection is promoted to 1; the existing generation 1 objects are never looked at and stay at generation 1.

If there isn't enough to be gained by just generation 0 objects then is can attempt a generation 1 collection. Any unused objects that are generation 0 or 1 will now be freed and the resulting memory compacted. This is a more intensive process than just a generation 0 collection.

Any surviving objects are promoted again - 1s become 2s and 0s become 1s. 2 being the highest generation in the current implementation. If there isn't enough to be gained from a generation 1 collection then it has to do a full collection (generation 2) which is considerably more work than either a 1 or 0 collection.

If you call GC.Collect() then you are forcing a generation 2 collection - this can result in a lot of objects getting promoted beyond their required generation and as a result they stay in memory longer.

As well as these three generations there is an additional 'large object heap' from which objects that exceed 85000 bytes are allocated - this heap is collected after a generation 2 collection but is never compacted.

As a starting guide .Net uses physical RAM as a guide for generation 2, while 0 and 1 are based on the cpu's level 1 and level 2 cache. Does that answer your question about the threshold? ;)

Additionally the GC comes in a couple of 'flavours' multiprocessor machines have a slightly different mechanism to single processor ones while a server based OS is tuned to a slightly different application profile to a desktop OS.

Also any object that has a finalizer registered will also survive it's first GC as it needs to have it's finalizer called to do clean up (this is why calling Dispose is recommended as it removes this step from the clean up process).
 
Back
Top