gpt4 book ai didi

Javafx WebEngine : what really happens in a background worker? UI 在 loadContent(大 HTML 文档)上挂起

转载 作者:搜寻专家 更新时间:2023-11-01 03:33:11 26 4
gpt4 key购买 nike

来自WebEngine文档:

Loading always happens on a background thread. Methods that initiate loading return immediately after scheduling a background job. To track progress and/or cancel a job, use the Worker instance available from the getLoadWorker() method.

我有一个 HTML string我通过 WebEngine.loadContent(String) 在 WebView 上加载它。该字符串大约有 500 万个字符长。在 Platform.runLater() 中运行它时(我必须在 JavaFX 线程中运行它,否则会出现错误)我的 UI 挂起大约一分钟。

如果我不在 Platform.runLater() 中运行它,我会得到:

java.lang.IllegalStateException: Not on FX application thread; currentThread = populator
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:236)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.web.WebEngine.checkThread(WebEngine.java:1216)
at javafx.scene.web.WebEngine.loadContent(WebEngine.java:931)
at javafx.scene.web.WebEngine.loadContent(WebEngine.java:919)
...

因为我必须,再次在挂起的 JavaFX 线程上运行它...

所以我必须等到页面加载,然后之前提交的任何Platform.runLater(()->webEngine.getLoadWorker().getProgress())(在网页加载过程中)会运行,每次给我 1.0...

我用来查询 Worker 的代码:

// WebView
wvIn.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
class ProgressThread extends Thread {
private Worker.State loadWorkerState;

synchronized Worker.State getLoadWorkerState() {
return loadWorkerState;
}

synchronized void setLoadWorkerState(Worker.State loadWorkerState) {
this.loadWorkerState = loadWorkerState;
}

{
setDaemon(true);
setName("LoadingWebpageProgressThread");
}

public void run() {
while (true) {
try {
if (getLoadWorkerState() == Worker.State.RUNNING)
// piWv ProgressIndicator (WebView loading)
Platform.runLater(() -> piWv.setVisible(true));
while (getLoadWorkerState() == Worker.State.RUNNING) {
Platform.runLater(() -> {
piWv.setProgress(wvIn.getEngine().getLoadWorker().getProgress());
// TODO delete
System.out.println(wvIn.getEngine().getLoadWorker().getProgress());
});
Thread.sleep(100);
}
if (getLoadWorkerState() == Worker.State.SUCCEEDED) {
Platform.runLater(() -> piWv.setProgress(1d));
Thread.sleep(100);
Platform.runLater(() -> {
piWv.setVisible(false);
piWv.setProgress(0d);
});
}
synchronized (this) {
wait();
}
} catch (InterruptedException e) {
}
}
}
};

final ProgressThread progressThread = new ProgressThread();
{
progressThread.start();
}

// executed on JavaFX Thread
@Override
public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {
if (newValue == State.SUCCEEDED) {
JSObject window = (JSObject) wvIn.getEngine().executeScript("window");
window.setMember("controller", mainController);
progressThread.setLoadWorkerState(newValue);
progressThread.interrupt();
} else if (newValue == State.RUNNING) {
progressThread.setLoadWorkerState(newValue);
progressThread.interrupt();
}
// TODO delete
System.out.println(oldValue + "->" + newValue);
}
});

有没有办法在后台线程中强制加载?

JavaFX 线程中到底发生了什么?是填充WebView的过程吗?

最佳答案

您在问题中显示的 HTML 文件几乎立即加载到我的机器上。

在我看来,问题出在您的代码中。好吧,这很麻烦。请让我指出它看起来不太好,因为它是 deadlock -prone,并使用异常来实现 guarded-blocks 的形式.

看来你没有完全理解 events 的概念.除非您为了简洁起见以某种方式切断了问题中的代码片段,否则 ProgressThread 实例是完全无用的。你已经有一个 ChangeListener根据需要分派(dispatch)事件,在 JavaFX 应用程序线程上执行回调;只需使用它。

indicator.setVisible(false); // Start hidden
engine.getLoadWorker().progressProperty().addListener((observable, oldValue, newValue) -> {
indicator.setProgress(newValue.doubleValue());
indicator.setVisible(indicator.getProgress() != 1D);
});

或者,您可以使用 binding 的强大功能:

Worker<Void> worker = engine.getLoadWorker();
indicator.visibleProperty().bind(worker.stateProperty().isEqualTo(Worker.State.RUNNING));
indicator.progressProperty().bind(worker.progressProperty());

对于您的 JavaScript 代码,我建议您监听文档事件而不是工作状态事件:它们在您的情况下更有意义,并且在页面实际完成呈现时触发它们,而不仅仅是在页面数据完成时触发下载中。

engine.documentProperty().addListener((observable, oldValue, newValue) -> {
if (newValue == null) {
return;
}
JSObject window = (JSObject)engine.executeScript("window");
window.setMember("controller", mainController);
});

请注意,在我的机器上,加载过程中进度似乎始终为零。我认为问题出在您的 HTML 代码中:如果您尝试加载一些其他资源,例如我们正在阅读的网页,进度指示器将提供更愉快的体验,在页面内容完成之前更新几次加载中。

关于Javafx WebEngine : what really happens in a background worker? UI 在 loadContent(大 HTML 文档)上挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41830701/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com