为了账号安全,请及时绑定邮箱和手机立即绑定

等待主框架加载时出现 JxBrowser TimeoutException

等待主框架加载时出现 JxBrowser TimeoutException

胡子哥哥 2022-11-02 15:41:46
我在一个项目中使用 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 completelyBrowser.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 -方法时,我的程序超时(下面的完整异常)例如,当我单击登录按钮并希望被转发到主视图时有一个小技巧,我偶然发现让它暂时工作(现在它变得令人毛骨悚然):当我在谷歌之间加载在线网页时,超时问题消失了也可以使用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.2019JxBrowser license valid.
查看完整描述

1 回答

?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

JxBrowser 基于 Chromium 引擎,继承了其多进程架构。每个Browser实例与至少一个处理 DOM 和 JavaScript 相关功能的渲染进程相关联。当您导航到不同的域时,Chromium 引擎会创建一个新的渲染进程并终止旧的渲染进程。如果您在一个域内导航,则呈现过程保持不变。


从调用堆栈中,我看到您尝试从 DOM 侦听器中加载 URL。DOM 侦听器是同步调用的,因此在 Java 处理事件时渲染进程保持阻塞。


当你加载一个 URL 时,例如 google.com,一切正常,因为一个新的渲染进程被创建,并且一旦页面被加载,该Browser.invokeAndWaitFinishLoadingMainFrame方法返回控制并且旧的渲染进程被终止。但是,如果您尝试加载file:///URL,则渲染过程保持不变,并且无法开始加载,因为渲染过程被Browser.invokeAndWaitFinishLoadingMainFrameDOM 侦听器调用的方法阻塞,因此您会遇到死锁。


为了避免此异常,您不应从 DOM 侦听器中启动同步导航。


根据调用堆栈,您loadView从DOMEventListener. 为了避免死锁,您应该异步调用此方法,例如:


import com.teamdev.jxbrowser.chromium.dom.events.DOMEvent;

import com.teamdev.jxbrowser.chromium.dom.events.DOMEventListener;


import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;


public class MyDomEventListener implements DOMEventListener {


    private final ExecutorService executorService;

    private final OrderCreationView view;


    public MyDomEventListener(OrderCreationView view) {

        this.view = view;

        this.executorService = Executors.newCachedThreadPool();

    }


    @Override

    public void handleEvent(DOMEvent domEvent) {

        // Do not block the current thread and invoke the loadView method asynchronously.

        executorService.execute(view::loadView);

    }

}

在该loadView方法中,您可以同步加载 HTML:


public void loadView() {

    Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {

        @Override

        public void invoke(Browser browser) {

            browser.loadHTML("");

        }

    });

    initLoginButton();

}


查看完整回答
反对 回复 2022-11-02
  • 1 回答
  • 0 关注
  • 72 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信