0

我创建了一个程序来读取串行端口、绘制数据并显示值。我正在使用 SwingWorker 来收集、检查和绘制值,同时允许用户在 GUI 中停止数据收集。当我尝试绘制值并显示确切值时,我相信我收到了修改异常。

下面是 doInBackground() 的简化版本。我擦除的行本质上是检查和比较读取的值。

protected Integer doInBackground() 
    while (true && !isCancelled()) {
        value = initandReadCOM();
        // I also check and compare the value
        publish(value);
    }
    return 0;
}

然后我使用process命令来绘制数据。我能找到的关于这个问题的最接近的线程建议使用这个。

@Override
protected void process(List<Float> chunks) {
    super.process(chunks);
    float factor = chunks.get(chunks.size() - 1);
    seriesUpdated = getSeries();
    SetDataField(factor);
    this.seriesUpdated.add(new Millisecond(), factor);
}

如果需要帮助诊断问题,下面列出了SetDataFieldand方法。seriesUpdated

public void SetDataField(float n) {
        this.data_.setText("Data: " + String.valueOf(n));
}

public TimeSeries getSeries() {
        return this.series;
}

随着程序运行时间的延长,此异常开始更频繁地出现。任何和所有的帮助将不胜感激。

另外,如果您需要其他帮助,请告诉我。谢谢

编辑:下面是堆栈跟踪

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at java.util.Collections$UnmodifiableCollection$1.next(Unknown Source)
    at org.jfree.chart.plot.XYPlot.drawRangeMarkers(XYPlot.java:4088)
    at org.jfree.chart.plot.XYPlot.draw(XYPlot.java:3281)
    at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1226)
    at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:1612)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
    at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
    at javax.swing.RepaintManager.paint(Unknown Source)
    at javax.swing.JComponent._paintImmediately(Unknown Source)
    at javax.swing.JComponent.paintImmediately(Unknown Source)
    at javax.swing.RepaintManager$3.run(Unknown Source)
    at javax.swing.RepaintManager$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$1000(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
4

1 回答 1

0

您正在修改 JFreeChart 的数据模型,而它可能会从 UI 线程中访问该模型以绘制它。要解决此问题,您有不同的选择:

  1. 让后台线程Collection独立于JFreeCharts 模型计算并将结果存储到 s 中。然后在 UI 线程中更新模型。这是最直接的方法,将图表模型视为 UI 部分,但您最终可能仍然在 UI 线程中做很多工作。

  2. 使用多个图表模型。更新与呈现的图表当前使用的不同的图表模型。然后通过在 UI 线程内的图表上设置新模型来更新 UI。这允许某些特定于图表的计算在后台线程中运行,并且可以通过对当前代码的最少更改来实现。但是,如果您有相当小的增量更改,因为每次更新都会重新计算整个图表模型,它可能会变得低效。

  3. 将整个图表代码移动到后台线程中。这可能是最激进但最有效的解决方案。在此解决方案中,UI 线程不再访问图表及其模型(或仅当确定后台线程不运行时)。相反,整个图表计算和渲染是在后台线程内部完成的BufferedImage。UI 线程将通过将先前渲染的图像blitting 到屏幕来进行绘画。UI 和后台线程之间的更新/同步只包括交换两个图像。

  4. 使用Lockorsynchronized块确保后台线程和 UI 线程仅在不同时间访问模型。由于您的背景威胁仅包含模型更新,因此这实际上就像根本没有多线程一样。我只是为了完整性添加了这个选项……</p>

于 2013-10-25T08:05:04.523 回答