3

Can someone tell me why the exitToolStripMenuItem_Click throws an InvalidOperationException. I know it happens due to plugin.Close() being called. However, I do not understand why. Closing the Form1 via the "X" button does not trigger the exception. Calling Application.Exit() does though. Below is a sample to demonstrate what is happening in my main app. In my main app events are triggered off certain forms closing so I need to make sure I call Close on each forms. I could change Application.Exit() to a Close() however after reading MSDN I don't feel like this is the correct solution. Any ideas would be helpful, thanks.

Note: The main application I'm working on is multi-threaded.

public partial class Form1 : Form
{
    Form plugin = new Form();
    public Form1()
    {
        InitializeComponent();
        plugin.Show();
    }

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        plugin.Close();
    }

    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Application.Exit();
    }
}

The exception thrown is:

Exception thrown: 'System.InvalidOperationException' in mscorlib.dll
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()
   at System.Windows.Forms.Application.ExitInternal()
   at System.Windows.Forms.Application.Exit(CancelEventArgs e)
   at System.Windows.Forms.Application.Exit()
   at WindowsFormsApplication2.Form1.exitToolStripMenuItem_Click(Object sender, EventArgs e)
Brian Boyd
  • 263
  • 1
  • 3
  • 11
  • Do not call Application.Exit, use the proper shutdown of your form (IE Close) – Steve Dec 21 '15 at 21:49
  • 1
    This is because you are trying to close the form in the closing event of it. By the time you get to the FormClosing event method, the Application.Exit() has already raised a close peition to the form. There is no need to call Close on FormClosing. – Cat_Clan Dec 21 '15 at 21:58
  • I changed the name of the form to plugin for less confusion. My main form needs to close all the plugins before exiting. The plugins might be in some state that would not be idle to just kill. From my understand Application.Exit is the correct method to call in a multi threaded application. If that is not true can someone point me to an msdn statement or another article that explains why i would use Close over Application.Exit. – Brian Boyd Dec 21 '15 at 22:51
  • @HenkHolterman I apologize i was trying to keep the code example simple and over looked that might effect the response. – Brian Boyd Dec 21 '15 at 23:01
  • When i say multithreaded I don't mean that the plugins are running on their own UI thread. They are all instantiated on main application thread. Each form may be running something on a background thread though. Each plugin handles its own cleanup when it is closed. I believe the question is still perfectly valid. The code above throws an exception. Based off msdn Application.Exit() appears to be the correct method to call, am I wrong? – Brian Boyd Dec 21 '15 at 23:20
  • here is a good posting you can reference the accepted answer here [SO Winforms - How to properly exit a C# Application](http://stackoverflow.com/questions/12977924/how-to-properly-exit-a-c-sharp-application) – MethodMan Dec 22 '15 at 00:07
  • Do you have more than one application context? Like 2 or more threads where you do `Application.Run(FormX)`. In that case Application.Exit cannot be used because it blindly iterates through all windows and tries to get their handle regardless of in which thread they were created. In that case you could rather keep track of your windows and call Close on them from their own threads (using `Invoke()`). – Louis Somers Jun 21 '18 at 14:21

1 Answers1

0

You don't need Application.Exit() in exitToolStripMenuItem_Click(). Calling Application.Exit, will close and dispose the form, while resuming the execution at exitToolStripMenuItem_Click, ObjectDisposedException would be thrown. Also, System.InvalidOperationException would be thrown as Windows Forms collection has been modified.

GianhTran
  • 3,443
  • 2
  • 22
  • 42