Chromium Embedded Framework中本机函数的后台处理



我正在Visual Studio 2013(C++)和Windows 8.1上测试一个CEF3程序。

我想处理从JavaScript调用的本机函数。但是,在执行本机函数时,浏览器会冻结。PostTask也无效。

在使用CreateThread(Win32 API)创建线程的情况下,在其他线程中获取Cef8Value时会发生错误。

没有什么好的异步处理函数的方法吗?

CefSettings settings;
settings.single_process = true;
void App::OnContextCreated(
    CefRefPtr<CefBrowser> browser,
    CefRefPtr<CefFrame> frame,
    CefRefPtr<CefV8Context> context) 
{
    CoInitializeEx(NULL, COINIT_MULTITHREADED);
    // Retrieve the context's window object.
    CefRefPtr<CefV8Value> object = context->GetGlobal();
    CefRefPtr<CefV8Handler> handler = new AppExtensionHandler(this);
    object->SetValue("execNative",
        CefV8Value::CreateFunction("execNative", handler),
        V8_PROPERTY_ATTRIBUTE_NONE);
}
bool AppExtensionHandler::Execute(const CefString& name,
    CefRefPtr<CefV8Value> object,
    const CefV8ValueList& arguments,
    CefRefPtr<CefV8Value>& retval,
    CefString& exception)
{
    CefRefPtr<CefBrowser> browser = CefV8Context::GetCurrentContext()->GetBrowser();
    if (!browser.get()) return false;
    if (name == "execNative") {
        Sleep(10000); // heavy process
        CefRefPtr<CefFrame> frame = browser->GetMainFrame();
        frame->ExecuteJavaScript(L"result(true)", frame->GetURL(), 0);
    }
    return true;
}

问题是javascript回调发生在CEF客户端的渲染进程上。这个过程直接负责所有的用户交互、点击、JS执行等等。即使你发布到另一个线程(在同一个过程中),看起来也没有太大的区别。

您想要做的是将其发送到浏览器进程并在那里进行处理。CEF3传真涵盖了这种通信,以防您以前不需要这样做:

[…]如何在浏览器和CEF3中的渲染进程之间发送信息

为了动态地提供信息,使用与特定CefBrowser实例相关联并且使用CefBrowser::SendProcessMessage()方法发送的进程消息(CefProcessMessage)。[…]从渲染进程发送到浏览器进程的消息将到达CefClient::OnProcessMessageReceived()。[…]

在Adobe Brackets Shell(一个相当流行的使用CEF3的开源WebIDE)中,这似乎是一件大事——他们的V8扩展指南很好地介绍了这一点。

无论何时调用本机函数,都会调用AppShellExtensionHandler::Execute()。此代码在呈现过程中运行,因此这里只应执行最琐碎的扩展代码。对于Brackets,此处仅处理getElapsedMilliseconds()。所有其他调用都通过CefProcessMessage传递给浏览器进程。

这里提到的AppShellExtensionHandler相当于您的AppExtensionHandler。我强烈建议仔细阅读他们的代码以进行扩展处理——这做得非常优雅公平警告:虽然Brackets.io是一家开源企业,但我在专业上与Adobe有关系

希望这能有所帮助——干杯!

看看这篇文章。它就像一个符咒。解决了我所有的JS到本机的问题,并使用结构化的参数传递方法。。它也正好解决了你所面临的问题。。。你只需要创建一个用户线程(Task)来处理后台的事情。。。

JS通过V8Context转换为本机-异步!

我自己测试过,效果非常好。。除非我错过了什么。。。

虽然这篇文章描述了C#,但应该非常直接地将其翻译为C++

相关内容

  • 没有找到相关文章

最新更新