等待加载主帧时的java JxBrowser TimeoutException(invokeAndWaitFinishLoadingMainFrame)
我正在一个项目中使用JxBrowser。我只处理本地HTML文件,因此使用以下方法呈现我的HTML文件:
public static void loadHTMLFile(Browser browser, String filename){
String current = PathUtils.getCurrentDir();
browser.loadURL("file:///" + current + "/some/path/in/my/project/resources/web/" + filename);
}
在某些情况下,我必须使用invokeAndWaitFinishLoadingMainFrame方法,因为我必须初始化必须首先完全加载的按钮
JxBrowser官方网站(https://jxbrowser.support.teamdev.com/support/solutions/articles/9000013107-loading-waiting)中的一个示例如下所示:
// Blocks current thread execution and waits until http://www.google.com web page is loaded completely
Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {
@Override
public void invoke(Browser value) {
value.loadURL("http://www.google.com");
}
});
在我的例子中,它看起来是这样的:
public static void loadHTMLFileComplete(Browser browser, String filename){
Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {
@Override
public void invoke(Browser value) {
loadHTMLFile(value, filename);
}
});
}
到目前为止我想没什么奇怪的
现在是棘手的部分:
invokeAndWaitFinishLoadingMainFrame方法存在以下问题:
- 第一个视图(登录视图)使用invokeAndWaitFinishLoadingMainFrame方法正确加载
- 之后,当再次使用invokeAndWaitFinishLoadingMainFrame方法时,我的程序超时(下面是完全异常)
- 例如,当我单击登录按钮并希望被转发到主视图时
我无意中发现了一个小技巧,让它暂时工作(现在它变得令人毛骨悚然):
- 当我加载介于两者之间的在线网页(如google)时,超时问题消失
- 也可以使用invokeAndWaitFinishLoadingMainFrame方法
我就是这样做的
public static void loadGoogle(Browser browser){ Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() { @Override public void invoke(Browser value) { value.loadURL("http://www.google.com"); } });
}
下面是我前面提到的timeoutException:
-- Product name: JxBrowser -- Licensed version: 6.x -- Licensed to: -- License type: Evaluation -- Generation date: 21.04.2019 -- Expiration date: 21.05.2019 -- License info: Single-user license -- Current date: 30.04.2019 JxBrowser license valid. 11:55:59 SCHWERWIEGEND:[0430/235559.671039:ERROR:sandbox_linux.cc(379)] InitializeSandbox() called with multiple threads in process gpu-process. com.teamdev.jxbrowser.chromium.Browser@6b9651f3 11:56:49 SCHWERWIEGEND: Unexpected exception in DOMEventListener.handleEvent() method. java.lang.RuntimeException: java.util.concurrent.TimeoutException at com.teamdev.jxbrowser.chromium.Browser.invokeAndWaitFinishLoadingMainFrame(SourceFile:570) at com.teamdev.jxbrowser.chromium.Browser.invokeAndWaitFinishLoadingMainFrame(SourceFile:532) at browserActions.PageLoader.loadHTMLFileComplete(PageLoader.java:15) at browserViews.OrderCreationView.loadView(OrderCreationView.java:21) at browserActions.ButtonInitializer.lambda$0(ButtonInitializer.java:26) at com.teamdev.jxbrowser.chromium.dom.internal.EventTarget$a.onMessageReceived(SourceFile:179) at com.teamdev.jxbrowser.chromium.internal.ipc.q.a(SourceFile:1085) at com.teamdev.jxbrowser.chromium.internal.ipc.r.run(SourceFile:69) at com.teamdev.jxbrowser.chromium.internal.s.run(SourceFile:79) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.util.concurrent.TimeoutException ... 14 more
总结如下:
它不起作用:
- 加载登录视图
- 单击登录按钮
- 尝试加载主视图->;超时
有效:
- 加载登录视图
- 单击登录按钮
- 加载谷歌
- 加载google后(用户没有时间进行交互),直接加载主视图->;没有超时
这里发生了什么:O
任何帮助都会很棒
# 1 楼答案
JxBrowser基于Chromium引擎并继承了其多进程体系结构。每个
Browser
实例都与至少一个处理DOM和JavaScript相关功能的渲染进程相关联。当您导航到另一个域时,Chromium引擎将创建一个新的渲染过程并终止旧的渲染过程。如果在一个域中导航,渲染过程将保持不变从调用堆栈中,我看到您试图从DOM侦听器中加载URL。DOM侦听器是同步调用的,因此在Java处理事件时,呈现过程仍然处于阻塞状态
当您加载URL时,例如google。com,一切正常,因为创建了一个新的呈现过程,并且在加载页面后,
Browser.invokeAndWaitFinishLoadingMainFrame
方法返回控件,旧的呈现过程被终止。但是,如果尝试加载file:///
URL,则呈现过程保持不变,无法启动加载,因为呈现过程被从DOM侦听器调用的Browser.invokeAndWaitFinishLoadingMainFrame
方法阻止,因此会出现死锁为了避免此异常,您不应该从DOM侦听器中启动同步导航
根据调用堆栈,可以从
DOMEventListener
调用loadView
方法。为了避免死锁,您应该异步调用此方法,例如:在
loadView
方法中,可以同步加载HTML: