【问题标题】:Dynamically remove and add components in vaadin from a thread从线程中动态删除和添加 vaadin 中的组件
【发布时间】:2023-12-29 08:11:01
【问题描述】:

我有一个 Vaadin 7 应用程序,它有一个通用布局,其中有一个按钮,它启动一个线程,执行一些计算。

有一个组件从计算中接收信息并显示进度信息等。

现在,当我启动应用程序并执行计算线程时,一切正常,视图构建正确。

当它完成并重新运行它时,只需再次按下开始按钮,我就会得到

Exception in thread "Thread-56" java.lang.IllegalStateException: A connector should not be marked as dirty while a response is being written.
at com.vaadin.ui.ConnectorTracker.markDirty(ConnectorTracker.java:505)
at com.vaadin.server.AbstractClientConnector.markAsDirty(AbstractClientConnector.java:141)
at com.vaadin.ui.AbstractComponentContainer.removeComponent(AbstractComponentContainer.java:227)
at com.vaadin.ui.AbstractOrderedLayout.removeComponent(AbstractOrderedLayout.java:178)
at com.test.pipeline.view.ResultPanel.rebuildResultLayout(ResultPanel.java:46)
at com.test.pipeline.view.ResultUIProcessListener.startTests(ResultUIProcessListener.java:40)
at com.test.pipeline.RanorexClient$RanorexWorker$$Lambda$224/988244250.accept(Unknown Source)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at com.test.pipeline.RanorexClient$RanorexWorker.inform(RanorexClient.java:99)
at com.test.pipeline.RanorexClient$RanorexWorker.run(RanorexClient.java:64)

RanorexoClient$RanorexWorker 是一个 Thread 进行计算。 有向工作人员注册的侦听器以获取通知。

所以我有一个线程链来更改 UI。

rebuildResultLayout 看起来像这样

void rebuildResultLayout() {
    mainLayout.removeComponent(resultLayout);
    resultLayout = new VerticalLayout();
    mainLayout.addComponent(resultLayout);
}

所以删除布局,创建新布局并再次添加。这是为了摆脱以前运行的信息 - 我也尝试过简单地resultLayout.removeAllComponents(),但这会导致同样的错误。

我在某处阅读以同步对 UI 的调用,所以目前我的 inform 方法看起来像这样

private void inform(Consumer<TestProcessListener> action) {
    synchronized (UI.getCurrent()) {
        processListeners.forEach(action);
    }
}

怎么了?必须做些什么来避免异常?

【问题讨论】:

  • 啊——我可能已经找到答案了:vaadin.com/docs/-/part/framework/advanced/advanced-push.html。使用ui.access 解决了我的问题。谁能验证这个观察现在不仅仅是运气?
  • 是的,这就是必需的。只需确保在您的后台线程中有一个有效的 UI 引用。使用分离线程时 UI.getCurrent() 并不总是存在

标签: java multithreading vaadin vaadin7


【解决方案1】:

https://vaadin.com/docs/-/part/framework/advanced/advanced-push.html 中所述,需要将ui 修改封装在ui.access() 调用中。

另请参阅@André Schild 评论,必须确保存在有效的 UI 引用

【讨论】: