khennadiy

Hi all!

I have an application that use Reflection to load some addins.

If I try Application.Restart() or Application.Exit() the result is an error:

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.Restart()
at frmMain.btnButton1_Click(Object sender, EventArgs e) in xxxxxxx

In OnFormClosing event i do this:

OnFormClosing

1. private void frmMain_FormClosing(object sender, FormClosingEventArgs e)

2. {

3. if (e.CloseReason == CloseReason.UserClosing)

4. {

5. this.Hide();
6. e.Cancel = true;

7. }

8. else

9. {

10. bool CanDispose = _pluginManager.RequireDispose();

11. if (CanDispose) _pluginManager.DisposePlugins();

12. e.Cancel = !CanDispose;

13. }

14. }

Where in lines 10-12 PluginManager asks all addins if they can be disposed immediately. If I comment lines 10-12 all works fine.

Please, does anybody know how to fix this



Re: Windows Forms General Application.Restart() raises InvalidOperationException

Jeris

I think the exception is resulting from '_pluginManager.RequireDispose' or '_pluginManager.DisposePlugins'. Thus, would you please display the codes of the functions RequireDispose and DisposePlugins





Re: Windows Forms General Application.Restart() raises InvalidOperationException

khennadiy

Hi, Jeris! Here is a code:

Code Block

struct PluginInfo

{

........................

public IPlugin Instance;

}

public interface IPlugin

{

........................

bool RequireDispose();

void Dispose();

........................

}

public class PluginManager

{

....................................

public bool RequireDispose()

{

bool CanDispose = true;

foreach (PluginInfo Plugin in this.Plugins)

{

try

{

bool Result = Plugin.Instance.RequireDispose();

if (Result == false)

{

CanDispose = false;

break;

}

}

catch (Exception exc)

{

_logger.Error(exc);

}

}

return CanDispose;

}

public void DisposePlugins()

{

foreach (PluginInfo Plugin in this.Plugins)

{

try

{

Plugin.Instance.Dispose();

}

catch (Exception exc)

{

_logger.Error(exc);

}

}

}

..............................

} // PluginManager

And if on of the plugins in RequireDispose show a MessageBox:

Code Block

class Plugin1 : IPlugin

{

.........................

public bool RequireDispose()

{

bool CanDispose = false;

bool Busy = true;

// Check if "Busy"

if (Busy)

CanDispose = (MessageBox.Show("Addin is busy. Dispose anywhere ",

"SMS", MessageBoxButtons.YesNo) == DialogResult.Yes);

else

CanDispose = true;

return CanDispose;

}

...................

public void Dispose()

{

// Dispose addin

}

}

Then we click on "Yes" button (addin is not really busy - its only a test), and call PluginManager.DisposePlugins(). After this method executed successfully (used a debugger) we exit from frmMain.OnFormClosing(...) method, and here is an exception!




Re: Windows Forms General Application.Restart() raises InvalidOperationException

Sergey Galich

This is wellknown error - you have foreach() and inside this you delete or add something to collection. Here is sample that make same result:

List<Plugin> data;
...
foreach(Plugin p in data)
{
data.Remove(p);
}



this will throw same error. I'm sure you have similar in your code. Perhaps you remove plugin from collection during foreach()





Re: Windows Forms General Application.Restart() raises InvalidOperationException

khennadiy

No, I don't modify a collection.

IPlugin.Dispose() method used for dispose internal plugin members and do some tasks on exit.

And, I test it with empty IPlugin.Dispose() method...




Re: Windows Forms General Application.Restart() raises InvalidOperationException

Sergey Galich

still I'm pretty sure you have foreach() and remove something from collection. Best way to find where - run in debugger, go to Debug\Exceptions menu and check Thrown column in CLR Exceptions line, so when exception is thrown you will see the right place.





Re: Windows Forms General Application.Restart() raises InvalidOperationException

khennadiy

Thank you, Sergey!

I rewrite my code and now MessageBox.Show calling from host form, not from the add-in, and all woking fine! Smile