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)
{
UpdateTempDelegate 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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With