开发者

Visual Studio Crashes! - Collection was modified after the enumerator was instantiated

Hey i have a UserControl that kept crashing my Visual Studio. So i ran another instance of VS and debugged the other VS and this is what i figured:

Collection was modified after the enumerator was instantiated.

Here is my array:

    private static Color[] colors = 
    {
        Color.FromArgb(155, 188, 255), //    40000
        Color.FromArgb(156, 189, 255), //    39500
        Color.FromArgb(157, 188, 255), //    39000
        Color.FromArgb(156, 189, 254), //    38500
    };

And here is my loop that crashes the bussines

    public Heater()
    {
        InitializeComponent();
        this.tarTemp = this.curTemp;
        new Thread(() => UpdateTemp(true)).Start(); 
    }

    private delegate void UpdateTempDelegate(bool loop);
    private void UpdateTemp(bool loop)
    {
        if (lblTemp.InvokeRequired)
        {
            UpdateTempDelegat开发者_如何学JAVAe del = new UpdateTempDelegate(UpdateTemp);
            lblTemp.Invoke(del, loop);
        }
        else
        {
            do
            {
                lblTemp.Text = curTemp + C;
                if (curTemp >= 0)
                {
                    int i = curTemp - 10;
                    if (i < 0)
                        i = 0;
                    if (i > colors.Length - 1)
                        i = colors.Length - 1;
                    this.BackColor = colors[i]; // I'M CRASHING !!!
                }
            } while (loop && !this.Disposing);
        }
    }

The line that crashes the Visual Studio Designer is this.BackColor = colors[i];

Here is the image of the running Threads:

Visual Studio Crashes! - Collection was modified after the enumerator was instantiated

All threads stopped on the same line... this.BackColor = colors[i];

Here is the EventViewer crash log:

Application: devenv.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.InvalidOperationException
Stack:
   at System.ThrowHelper.ThrowInvalidOperationException(System.ExceptionResource)
   at System.Collections.Generic.SortedList`2+SortedListValueEnumerator[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].MoveNext()
   at Microsoft.VisualStudio.Shell.ServiceProviderHierarchy.GetService(System.Type)
   at System.ComponentModel.Design.ServiceContainer.GetService(System.Type)
   at System.ComponentModel.Design.DesignerHost.GetService(System.Type)
   at System.ComponentModel.Design.DesignerHost+Site.System.IServiceProvider.GetService(System.Type)
   at System.Windows.Forms.Control.get_AmbientPropertiesService()
   at System.Windows.Forms.Control.get_BackColor()
   at System.Windows.Forms.Control.set_BackColor(System.Drawing.Color)
   at Multiplier.Heater.UpdateTemp(Boolean)
   at Multiplier.Heater.<.ctor>b__0()
   at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.ThreadHelper.ThreadStart()

This is the weirdest thing i encountered so far. Help whould be appriciated.


As you found out, your code is crashing the designer, taking VS down with it. The problem is that you start a thread in design mode, triggered by the designer running some of your code at design time. It for example will run the constructor, the Load event, OnHandleCreated, etcetera. That makes for a very nice design-time experience, your control will look just like it does at runtime.

But that can also cause plenty of problems. You have to avoid running code that may cause an exception when it runs in a different execution context. Classic examples are trying to open a file without specifying the full path, opening a dbase connection with the dbase server offline or unreachable. And definitely starting a thread, InvokeRequired is not going to reliably work as the designer constructs and destroys the native window handle. The fix is simple:

public Heater()
{
    InitializeComponent();
    this.tarTemp = this.curTemp;
    if (!this.DesignMode) {
        new Thread(() => UpdateTemp(true)).Start(); 
    }
}

You'll need to do more work, this code won't work well at runtime either. The threaded code will bomb when the form on which the user control is placed is closed. Once you fix that, odds are good that it now works correctly at design-time as well. But don't.


Are you modifying the collection using any other code? Usually this happens when you are enumerating a collection in a loop and you try to modify the collection.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜