从线程动态删除和添加vaadin中的组件
Dynamically remove and add components in vaadin from a thread
我有一个 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$$Lambda4/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);
}
}
怎么了?必须做什么才能避免异常?
如 https://vaadin.com/docs/-/part/framework/advanced/advanced-push.html 中所述,需要 uired 将 ui 修改包装在 ui.access()
调用中。
另请参阅@André Schild 评论,必须确保存在有效的 UI 引用
我有一个 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$$Lambda4/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);
}
}
怎么了?必须做什么才能避免异常?
如 https://vaadin.com/docs/-/part/framework/advanced/advanced-push.html 中所述,需要 uired 将 ui 修改包装在 ui.access()
调用中。
另请参阅@André Schild 评论,必须确保存在有效的 UI 引用