此处针对的是一个CefClient管理多个CefBrowser的情景。
情景实现步骤:进入百度首页=》新闻=》随便点击一个新闻(此时会创建一个新CefBrowser,cef默认是popup,我们修改为WS_CHILD,实现多标签页,具体实现下一章介绍)

cefsample的实例中我们知道了cefclient的生命周期需要自己管理,并且在退出的时候调用CefBrowserHost::CloseBrowser(false)或者CefBrowserHost::TryCloseBrowser(),随后触发DoClose(注意:DoClose调用之后OnBeforeClose并不是一定被调用,这个和CefClient的生命周期有关

在Cef多标签浏览器的时候我们实现了CloseAllBrowsers,OnAfterCreated,OnBeforeClose实现CefClient生命周期管理。代码如下(有问题代码):

void CBrowserHandler::CloseAllBrowsers()
{if (!CefCurrentlyOn(TID_UI)){// Execute on the UI thread.// bind ref cef_closure_taskCefPostTask(TID_UI, base::Bind(&CBrowserHandler::CloseAllBrowsers, this));return;}if (m_browser_list.empty())return;std::vector<CefRefPtr<CefBrowser> >::const_iterator it = m_browser_list.begin();for (it; it != m_browser_list.end(); ++it)(*it)->GetHost()->TryCloseBrowser();// CloseBrowser(force_close);}bool CBrowserHandler::DoClose(CefRefPtr<CefBrowser> browser)
{CEF_REQUIRE_UI_THREAD();m_is_closing = (m_browser_list.size() <= 0);return false;
}void CBrowserHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{CEF_REQUIRE_UI_THREAD();// Remove from the list of existing browsers.std::vector<CefRefPtr<CefBrowser> >::iterator bit = m_browser_list.begin();for (; bit != m_browser_list.end(); ++bit) {if ((*bit)->IsSame(browser)) {m_browser_list.erase(bit);break;}}
}

测试结果:多标签的时候程序关闭不了,原因:m_is_closing 始终为false。N个标签的时候虽然系统调用了N次DoClose,但是OnBeforeClose却一次也没有调用,所以m_is_closing 的条件始终不会成立。

修改代码,把删除操作放在DoClose里面管理,代码如下:

void CBrowserHandler::CloseAllBrowsers()
{if (!CefCurrentlyOn(TID_UI)){// Execute on the UI thread.// bind ref cef_closure_taskCefPostTask(TID_UI, base::Bind(&CBrowserHandler::CloseAllBrowsers, this));return;}if (m_browser_list.empty())return;std::vector<CefRefPtr<CefBrowser> >::const_iterator it = m_browser_list.begin();for (it; it != m_browser_list.end(); ++it)(*it)->GetHost()->TryCloseBrowser();// CloseBrowser(force_close);}bool CBrowserHandler::DoClose(CefRefPtr<CefBrowser> browser)
{CEF_REQUIRE_UI_THREAD();std::vector<CefRefPtr<CefBrowser> >::iterator bit = m_browser_list.begin();for (; bit != m_browser_list.end(); ++bit) {if ((*bit)->IsSame(browser)) {m_browser_list.erase(bit);break;}}m_is_closing = (m_browser_list.size() <= 0);return false;
}void CBrowserHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{CEF_REQUIRE_UI_THREAD();
}

运行结果:
为什么会迭代器无效呢?调试发现

for (it; it != m_browser_list.end();++it)(*it)->GetHost()->TryCloseBrowser();// CloseBrowser(force_close);

for关闭浏览器的的时候会触发DoClose,此时DoClose里面删除了元素导致迭代器失效。此时当再次操作迭代器it的时候就会触发异常了。所以修改CloseAllBrowsers代码如下:

void CBrowserHandler::CloseAllBrowsers()
{if (!CefCurrentlyOn(TID_UI)){// Execute on the UI thread.// bind ref cef_closure_taskCefPostTask(TID_UI, base::Bind(&CBrowserHandler::CloseAllBrowsers, this));return;}if (m_browser_list.empty())return;//建立一个副本操作std::vector<CefRefPtr<CefBrowser> > temp_browser_list = m_browser_list;std::vector<CefRefPtr<CefBrowser> >::const_iterator it = temp_browser_list.begin();for (it; it != temp_browser_list.end(); ++it)(*it)->GetHost()->TryCloseBrowser();// CloseBrowser(force_close);
}

运行结果和预期一致。但是调试的过程发现一个新问题?理论上调用一次CloseAllBrowsers就应该关闭所有的CefClient,即:for N次TryCloseBrowser触发N次DoClose。但是结果只调用了一次,而且是触发的最后一个调用对象的DoClose(DoClose会再次触发WM_CLOSE)(对象只有第一次调用TryCloseBrowser才会触发DoClose,后面再次调用都不会再触发DoClose)。(由于cef源码没有编译,所以这里暂时不知道为什么会这样,如果知道的大神请告诉一下)。

作者:cqclark
来源:CSDN
原文:https://blog.csdn.net/cqclark/article/details/49121027
版权声明:本文为博主原创文章,转载请附上博文链接!
如果浏览器是其他窗口的父窗口,那么这个关闭事件会引起父窗口的系统函数调用。那父窗口需要调用 CloseBrowser(false) 并等待第二个系统调用的关闭事件来指示浏览进程允许关闭。
如果关闭通过Javascript事件或DoClose()回调函数处理,那第二个系统关闭事件就不会被发送。
IsClosing()测试是否关闭,如果是第一次的系统关闭事件就返回false,每二次返回true;


所以最终修改代码如下:

void CBrowserHandler::CloseAllBrowsers()
{if (!CefCurrentlyOn(TID_UI)){// Execute on the UI thread.// bind ref cef_closure_taskCefPostTask(TID_UI, base::Bind(&CBrowserHandler::CloseAllBrowsers, this));return;}if (m_browser_list.empty())return;//一次只能关闭一个CefBrowser=》DoClose,即使关闭多个也只会调用一次DoClosestd::vector<CefRefPtr<CefBrowser> >::const_iterator it = m_browser_list.begin();if (it != m_browser_list.end())(*it)->GetHost()->TryCloseBrowser();// CloseBrowser(force_close);}bool CBrowserHandler::DoClose(CefRefPtr<CefBrowser> browser)
{CEF_REQUIRE_UI_THREAD();std::vector<CefRefPtr<CefBrowser> >::iterator bit = m_browser_list.begin();for (; bit != m_browser_list.end(); ++bit) {if ((*bit)->IsSame(browser)) {m_browser_list.erase(bit);break;}}m_is_closing = (m_browser_list.size() <= 0);return false;
}void CBrowserHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{CEF_REQUIRE_UI_THREAD();
}

此时多标签浏览器可以正常关闭并且没有进程驻留

CEF CloseBrowser相关推荐

  1. VS2019 VC++ MFC CEF(Chrome)开发环境搭建及相关功能demo(附源码)

    本文章主要介绍CEF如何作为一个控件,加在MFC的窗体中,并实现一些功能,如:打开指定网址.刷新.后退关闭子窗口或页签.关闭全部页签/子窗口和主窗体.浏览器界面自适应窗口大小等等,也会交代会遇到的一些 ...

  2. CEF 关闭流程优化

    CEF的详细关闭流程参考:https://blog.csdn.net/louis_815/article/details/76269057 通过上述博客我们首先需要明白WM_CLOSE,会在什么情况下 ...

  3. Cef功能开发经验总结

    转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/70159672 这是我开发Cef功能时对踩过的坑,进行的总结,话说Cef坑 ...

  4. CEF源码编译和生产库的使用

    CEF版本是Branch 2171 开发环境是VS2012 查看一下libcef_dll_wrapper工程属性,确定Code Generation 选择MTD(Debug) 或者MT(Release ...

  5. cef在android中使用_嵌入Chrome cef之完整版(本教程基于cef1)

    本教程基于cef1 至于cef1与cef3的区别请参考 http://blog.csdn.NET/tts2game/article/details/17260865 总结之前先将我的参考资料整理如下 ...

  6. CEF(包含均衡负载)

    (转自: http://baike.baidu.com/view/51048.htm) 传统路由器的基本作用是路由计算和包转发,通常基于共享存储器体系结构,采和集中式CPU,即单个CPU(或多个CPU ...

  7. Cygwin编译cef

    1.下载cygwin,并安装如下项: autobuild autoconf autogen automake ccrypt cmakegcc-g++gdb httpd libGLw-devel lib ...

  8. C#搭建CEF(CEFGLUE) 环境。

    CEF(CEFGLUE)如果想做浏览器的,对这个应该不陌生了,相关资料执行百度了,现在写这文章这是按当前时间做一个环境搭建时所需要的资料的一个收集. 1:下载Xilium.CefGlue项目源码. 链 ...

  9. cef使用缓存_CEF 文件下载功能实现

    CEF 下载功能非常容易拓展,它提供了丰富的接口和控制功能,比如对正在下载的文件实现暂停.继续.取消等操作.并且 CEF 还帮我们默认实现了一个另存为的对话框,如果不是必须你甚至都不需要去自己实现这个 ...

最新文章

  1. deepspeaker(TensorFlow)百度声纹识别和对比代码和模型
  2. 「Swift」第三章String and Character
  3. double小数点后最多几位_花了这么多冤枉钱后,我最喜欢这4款医美氨基酸洗面奶...
  4. Angular Injector.create的工作原理
  5. Jquery中如何获取元素的文本,值,属性和内容
  6. 万字总结!java让字符串反转
  7. Spring Boot中对log4j进行多环境不同日志级别的控制
  8. 存储过程是用来干什么的_感情不是用来考验的
  9. Mstsc、Telnet、SSH之间的区别
  10. Linux Server - NIS
  11. Java:关于负数的向上转型
  12. css小球落地阴影,CSS3球体掉落动画带阴影效果
  13. ScreenFlow Mac 苹果电脑视频录制编辑录屏软件 中文版v8.2.2
  14. android studio 融云,融云 SDK 集成详解 – Android Studio
  15. 计算机科学与技术职业规划1000字,计算机职业生涯规划书1000字
  16. spring中cglib动态代理
  17. 深度学习之基于Tensorflow2.0实现VGG16网络
  18. Some file crunching failed, see logs for details解决方案 以及.9patch点9图片的报错的详细修改方法
  19. USB手机数据线充电线电源线出口办理CE认证的流程
  20. 我是如何写出一本畅销技术书的

热门文章

  1. win10 绿色版gsql启动卡住_Win10优化软件Windows 10 Manager+MP3剪切合并大师 优化版
  2. 创业公司 vs. 大公司
  3. c++socket双人聊天
  4. YoloV8改进策略:InternImage与YoloV8深度融合,动态卷积DCNv3大显神威
  5. 记:《洛克菲勒留给儿子的38封信》-- 36
  6. 解除微软系统正版验证
  7. 浅谈个人发展经历,明确自己发展方向
  8. 基于栅格地图的路径规划(一)基于Matlab二维、三维栅格地图的构建
  9. citespace:时间线聚类标签显示不完全时
  10. linux环境下如何卸载一路赚钱(yilu/mservice)