I'm having an issue closing a program when there is a large amount of dialogs open. I was able to reproduce the bug using the following functions. The parent form on which this runs on is created using Application.Run(mainform).
When button1 is clicked, it creates a very basic form that opens another dialog of itself when "ok" is pressed. It then initiates the OnShutdown() function. This waits 15 seconds, then attempts to close all windows and exit the program. When more than 6 dummy windows are open, the function closes all the dummy windows but not the main window.
The steps for me reproducing the problem is:
- Click button1
- Close created heavy dialog
- Click on on the msgbox
- Click on button1 again
- On the new heavy dialog, I press Ok to open another heavy dialog
- Continue to open more heavy dialog, until 6-10 are open concurrently
Once the 15 seconds are up, all the dialogs close, but the parent form remains open, when it should be closed.
private void button1_Click(object sender,EventArgs e) { BasicTemplate heavy = new BasicTemplate(); heavy.ShowDialog(); OnShutdown(); } private void OnShutdown() { timerSignals.Enabled=false;//quit receiving signals. string msg = ""; msg+=Process.GetCurrentProcess().ProcessName+" "; msg+=Lan.g(this,"will shut down in 15 seconds. Quickly click OK on any open windows with unsaved data."); MsgBoxCopyPaste msgbox = new MsgBoxCopyPaste(msg); msgbox.Size=new Size(300,300); msgbox.TopMost=true; msgbox.Show(); ODThread killThread = new ODThread((o) => { Thread.Sleep(15000);//15 seconds //Also happens with BeginInvoke() Invoke((Action)(() => { CloseOpenForms(true); })); Thread.Sleep(1000);//1 second Invoke((Action)Application.Exit); }); killThread.Start(true); return; } public void Start(bool isAutoCleanup) { _isAutoCleanup=isAutoCleanup; if(_thread.IsAlive) { return;//The thread is already running. } if(_hasQuit) { return;//The thread has finished. } _dateTimeStart=DateTime.Now; _thread.Start(); } //Code for "OK" button on the heavy dialog created above private void butOK_Click(object sender,EventArgs e) { BasicTemplate formp = new BasicTemplate(); formp.ShowDialog(); } private bool CloseOpenForms(bool isForceClose) { for(int f=Application.OpenForms.Count-1;f>=0;f--) { //Count backwards to avoid out of bounds if(Application.OpenForms[f]==this) { continue; } Form openForm=Application.OpenForms[f];//Copy so we have a reference to it after we close it. openForm.Hide(); if(isForceClose) { openForm.Dispose(); } else { openForm.Close();//Attempt to close the form if(openForm.IsDisposed==false) { openForm.Show();//Show that form again return false; } } } return true; }
When line 3's "heavy.ShowDialog()" is changed to "heavy.Show()", the holdup no longer takes place. When multiple heavy dialogs are opened using a different button, the issue no longer takes place (up to ~20 new dialogs).
The shutdown sequence is run as a thread to allow the user to save any changes they have made before the program's database updates. I'm not sure if what I've implemented correctly shows the bug, but it at least produces similar events.