• CefSharp 实现多标签页 调用ChromiumWebBrowser的SetAsPopup()后浏览页卡死,的另一种解决方案


    最进想使用WPF+CefSharp实现浏览器多标签页, 所以直接实现ILifeSpanHandler接口添加窗口处理,但是在OnBeforePopup方法中,设置好窗口句柄后触发弹出新页时发现一个尴尬的问题:

    问题

    OnBeforePopup方法中调用SetAsPopup()方法,会导致浏览器首页卡死(仅在WPF中发现,Winform不会),新窗口页正常操作(后续窗口页中都不会有这个问题)。

    如果不调用SetAsPopup()方法,会导致新窗口页的事件全部失效(处理器不会),比如TitleChanged事件在浏览器标题更改后,需要及时更新浏览器标题到控件上,这样就无法触发浏览器标题更改事件(TitleChanged)。

    解决办法

    既然调用SetAsPopup会卡死,那我们就不调用,但是不调用SetAsPopup会导致新打开的窗口页事件丢失,那就想办法手动实现这个方法的一部分功能(赋值事件、处理器等信息)。

    SetAsPopup方法中最后有一个out IWebBrowser newBrowser 参数,这个参数作用是新打开窗口页的浏览器对象需不需要我们提供,一般设置这个参数为null,不需要我们提供。

    如果不为null时,新窗口浏览器对象将使用newBrowser作为新窗口页的浏览器对象。

            public bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, 
    out
    IWebBrowser newBrowser) {

    所以在方法中显示给newBrowser赋上值,(相当于实现一部分SetAsPopup方法工作...): 

    public class CefLifeSpanHandler : ILifeSpanHandler
    {
        //省略其他ILifeSpanHandler接口实现方法...

    //构造函数传入窗口对象,方便控制窗口中的控件 MainWindow mainWindow; public CefLifeSpanHandler(MainWindow _mainWindow) { this.mainWindow = _mainWindow; }   //浏览器新窗口弹出时调用方法 public bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser) { //为新弹窗创建一个浏览器对象 ChromiumWebBrowser newChromeBrowser = new ChromiumWebBrowser(); //为新弹窗复制窗口处理 newBrowser.LifeSpanHandler = this; //省略赋值其他处理器... //赋值标题修改事件 newChromeBrowser.TitleChanged += mainWindow.Chrome_TitleChange; //省略赋值其他事件.... //留下创建的浏览器对象引用,windowList(List<ChromiumWebBrowser>)是在MainWindow下声明的变量,窗口关闭时要释放,不然退出程序会跨线程访问控件错误 mainWindow.windowList.Add(newChromeBrowser); //为浏览器赋值 newBrowser = newChromeBrowser; //.... return false; } }

    到这里,在新窗口页打开时,即触发了标题修改事件,又没有导致浏览器首页卡死,但在关闭窗口时,会报跨线程访问错误,需要在窗口关闭时释放掉创建的窗口浏览器对象:

    private void Window_Closed(object sender, EventArgs e)
    {
        //释放每一个chrome窗口资源
        for (int i = 0; i < windowList.Count; i ++)
        {
            windowList[i].Dispatcher.Invoke(delegate {
                windowList[i].Dispose();
            });
        }
    }

    到这里,基本上解决了阻止浏览器弹窗时调用 SetAsPopup 首页卡死问题。

    如果本人有理解不对的地方,希望前辈们评论区指导,非常感谢!

  • 相关阅读:
    scikitlearn中predict_proba用法 (与predict的区别)
    Sklearn,TensorFlow,keras模型保存与读取
    TensorFlow GPU 的使用
    Keras2.2 predict和fit_generator的区别
    wordcloud词云可视化
    使用scp命令,远程上传下载文件/文件夹
    L0/L1/L2范数的联系与区别
    Python中的正斜杠/与反斜杠\
    在Keras中使用tensorboard可视化acc等曲线
    Linux终端没有GUI,使用matplotlib绘图
  • 原文地址:https://www.cnblogs.com/GengMingYan/p/14357714.html
Copyright © 2020-2023  润新知