【问题标题】:VB exception Collection was modified; enumeration operation may not executeVB异常集合被修改;枚举操作可能无法执行
【发布时间】:2020-03-07 07:10:18
【问题描述】:

我正在尝试学习 VB 编程,并且一直在使用带有 Visual Basic Forms PC GUI 的 Arduino 进行云检测项目。我已经取得了很大的进步,但是我偶尔会遇到错误:

************** Exception Text **************
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.ThrowHelper.ThrowInvalidOper ationException(ExceptionResource resource)
at System.Collections.Generic.List`1.E numerator.MoveNextRare()
at System.Collections.Generic.List`1.E numerator.MoveNext()
at System.Windows.Forms.DataVisualizat ion.Charting.ChartTypes.LineChart.P rocessChartType(Boolean selection, ChartGraphics graph, CommonElements common, ChartArea area, Series seriesToDraw)
at System.Windows.Forms.DataVisualizat ion.Charting.ChartTypes.LineChart.P aint(ChartGraphics graph, CommonElements common, ChartArea area, Series seriesToDraw)
at System.Windows.Forms.DataVisualizat ion.Charting.ChartArea.Paint(ChartG raphics graph)
at System.Windows.Forms.DataVisualizat ion.Charting.ChartPicture.Paint(Gra phics graph, Boolean paintTopLevelElementOnly)
at System.Windows.Forms.DataVisualizat ion.Charting.Chart.OnPaint(PaintEve ntArgs e)
at System.Windows.Forms.Control.PaintW ithErrorHandling(PaintEventArgs e, Int16 layer)
at System.Windows.Forms.Control.WmPain t(Message& m)
at System.Windows.Forms.Control.WndPro c(Message& m)
at System.Windows.Forms.Control.Contro lNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.Contro lNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.C allback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

我在 Google 上花了很多时间试图了解问题并找到解决方案,但是我没有足够的经验来实施解决此问题所需要做的事情。我认为问题在于更新用于在我的 PC GUI 上显示三个图表的数据。我猜数据正在与绘制图表的线程不同的线程中更新,但我不清楚如何处理这个问题。

我的代码分为一系列子程序:

ProcessData() ' do the basic calcs
CloudCalcs() ' do the cloud calculations
UpdateHistory() ' update the graphs

图形更新的子程序是:

Private Sub UpdateHistory()
time = TimeOfDay() ' retrieves current system time (used for plot x axis)
Chart1.Series("Series1").Points.Add XY(time, cloud)
Chart2.Series("Series1").Points.Add XY(time, light)
Chart3.Series("Series1").Points.Add XY(time, wind)

If HistoryFull = False Then
j = j + 1
End If

' this starts removing the oldest data points when the required number of points have been added to the history

If j > hpt Then
HistoryFull = True
Chart1.Series("Series1").Points.RemoveAt(0)
Chart2.Series("Series1").Points.RemoveAt(0)
Chart3.Series("Series1").Points.RemoveAt(0)
End If

End Sub

如果有人能指导我如何解决这个问题,我将不胜感激。

谢谢,

彼得

【问题讨论】:

  • 哪一行抛出异常?
  • 您是否设置了Control.CheckForIllegalCrossThreadCalls Property = False?如果是这样,这不是从辅助线程处理 UI 的可接受方式。
  • 我不确定哪一行会引发异常 - 我该如何确定?
  • 代码包括检查非法跨线程调用的行: Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False
  • Control.CheckForIllegalCrossThreadCalls 周围的文档充其量是非常糟糕的,因为它建议将其设置为 false 以防止非法跨线程控制访问异常,但您永远不应将此属性设置为 False。您可以按照this example 中使用的模式从辅助线程安全地访问控件。

标签: vb.net


【解决方案1】:

得到了一些帮助 - 这很有效:

Private Sub UpdateHistory()

    time = TimeOfDay() ' retrieves current system time (used for plot x axis)

    AddDataPoint(Chart1, time, cloud)
    AddDataPoint(Chart2, time, light)
    AddDataPoint(Chart3, time, wind)

    If HistoryFull = False Then
        j = j + 1
    End If

    If j > hpt Then
        HistoryFull = True

        RemoveDataPoint(Chart1)
        RemoveDataPoint(Chart2)
        RemoveDataPoint(Chart3)

    End If

End Sub

Friend Delegate Sub RemoveDataPointCallback(ByRef chart As Chart)
Private Sub RemoveDataPoint(ByRef chart As Chart)

    If chart.InvokeRequired Then
        Dim callback As RemoveDataPointCallback = New RemoveDataPointCallback(AddressOf RemoveDataPoint)
        Me.Invoke(callback, New Object() {chart})
    Else
        chart.Series("Series1").Points.RemoveAt(0)
    End If

End Sub


Friend Delegate Sub AddDataPointCallback(ByRef chart As Chart, chartTime As Date, chartData As Double)
Private Sub AddDataPoint(ByRef chart As Chart, chartTime As Date, chartData As Double)

    If chart.InvokeRequired Then
        Dim callback As AddDataPointCallback = New AddDataPointCallback(AddressOf AddDataPoint)
        Me.Invoke(callback, New Object() {chart, chartTime, chartData})
    Else
        chart.Series("Series1").Points.AddXY(chartTime, chartData)
    End If

End Sub

【讨论】:

    猜你喜欢
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-17
    相关资源
    最近更新 更多