modifying DocumentIndicatorCollection causes unhandled excep

SyntaxEditor for Windows Forms Forum

Posted 14 years ago by Oliver Mellet
Avatar
I'm getting an exception when modifying the Document.Indicators collection while a CompilerErrorIndicator is visible. This is happening because I have a seperate thread add/removing elements with this list while the user edits code. I'm wrapping the Document.Indicators.Add and .Remove in a lock statement, but apparently the rendering code isn't locking that collection before iteration. I get a fatal error and a big red X in the control area when I click "continue".


System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.ArrayListEnumeratorSimple.MoveNext()
at ActiproSoftware.SyntaxEditor.EditorView._1(Graphics , Rectangle , DocumentLine , Int32 , DisplayLine , _56 , Rectangle , Int32 )
at ActiproSoftware.SyntaxEditor.EditorView._2(Graphics , Rectangle )
at ActiproSoftware.SyntaxEditor.EditorView.OnRender(PaintEventArgs e)
at ActiproSoftware.WinUICore.UIElement.Render(PaintEventArgs e)
at ActiproSoftware.WinUICore.UIControl.OnRenderChildElements(PaintEventArgs e)
at ActiproSoftware.WinUICore.UIControl.Render(PaintEventArgs e)
at ActiproSoftware.WinUICore.UIControl._1(PaintEventArgs )
at ActiproSoftware.WinUICore.UIControl.OnPaint(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at ActiproSoftware.SyntaxEditor.SyntaxEditor.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Comments (14)

Posted 14 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
What do you suggest we do? When painting there are several places where we have to iterate through the collection. Would locking it slow down the painting?


Actipro Software Support

Posted 14 years ago by Oliver Mellet
Avatar
I'd suggest locking the collection during iteration, or failing that, throw an exception if the collection is modified on a different thread than the UI thread. Locking shouldn't slow it down too much, tho.
Posted 14 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
How about if we just changed the one statement from a foreach() to a for() instead... Think that would work around the problem?


Actipro Software Support

Posted 14 years ago by Oliver Mellet
Avatar
That may work, but do you really want the collection changing in the middle of a for loop? You could concievably be drawing an error that's already been removed from the collection by another thread. Why is locking the collection an issue?
Posted 14 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
So would you recommend that as we draw each line, put something like this around the code that draws the line:

lock (documentLine.Indicators) {
// Drawing code here
}


Actipro Software Support

Posted 14 years ago by Oliver Mellet
Avatar
Actually, it should be:
lock (documentLine.Indicators.SyncRoot) {
// Drawing code here
}
But yea, that's how I'd do it.
Posted 14 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Ok, the lock is in the next release.


Actipro Software Support

Posted 13 years ago by Nigel
Avatar
What version do I need for this to be corrected? I have synclocks around my indicators.Clear and indicators.Add but I get exactly the same issue as here (fails when rendering)

I have been using the SquiggleLine and have across exactly the same problem - changing it to a Compiler made no difference.
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
It was added a while ago. Just download the latest maintenance release from your Organization Purchases page.


Actipro Software Support

Posted 13 years ago by Nigel
Avatar
Yes I tried that. I am on version 3.1.210.0 and at a bit of a loss now.

I'm getting the following exception so any ideas would be great.

at System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()
at ActiproSoftware.SyntaxEditor.EditorView.a(Graphics A_0, Rectangle A_1, DocumentLine A_2, Int32 A_3, DisplayLine A_4, az A_5, Rectangle A_6, Int32 A_7)
at ActiproSoftware.SyntaxEditor.EditorView.b(Graphics A_0, Rectangle A_1)
at ActiproSoftware.SyntaxEditor.EditorView.OnRender(PaintEventArgs e)
at ActiproSoftware.WinUICore.UIElement.Render(PaintEventArgs e)
at ActiproSoftware.WinUICore.UIControl.OnRenderChildElements(PaintEventArgs e)
at ActiproSoftware.WinUICore.UIControl.Render(PaintEventArgs e)
at ActiproSoftware.WinUICore.UIControl.a(PaintEventArgs A_0)
at ActiproSoftware.WinUICore.UIControl.OnPaint(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at ActiproSoftware.SyntaxEditor.SyntaxEditor.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
at System.Windows.Forms.Form.ShowDialog()
at
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Are you able to duplicate this in a simple project? It would be great if we could debug it to figure out what is happening.

With the lock in place, you should be able to update indicators in a secondary thread. Are you updating anything else as well?


Actipro Software Support

Posted 13 years ago by Nigel
Avatar
Yes, I can replicate the problem in a simple project

The project simply has a SyntaxEditor on a form. A timer fires on the form every few seconds causing an instance of a parser object to raise an error eventarg for each error it finds. The form handles the event and add an Indicator. In the handler is an Synclock on the indicators collection of the document on the editor.

(can send it over - where to?)
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Send it over to our support address.


Actipro Software Support

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Thanks for the sample project Nigel. We've changed the looping code for drawing indicators to try and work around this.

For anyone else reading this, Nigel tried out the changed code (which will be in the next maintenance release) and thinks it resolved the issue but will do more testing later.


Actipro Software Support

The latest build of this product (v2018.1 build 0341) was released 3 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.