Chromium Embedded Framework中本机功能的后台流程

时间:2014-04-23 12:40:28

标签: javascript c++ multithreading chromium chromium-embedded

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

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

如果线程是使用CreateThread(Win32 API)创建的,则在其他线程中获取CefV8Value时会发生错误。

有没有以异步方式处理函数的好方法?

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;
}

2 个答案:

答案 0 :(得分:4)

问题是javascript回调发生在CEF客户端的渲染过程上。该过程直接负责所有用户交互,点击,JS执行等。即使你发布到另一个帖子(在同一个过程中),它似乎没有产生巨大的差异。

您要做的是将其发送到浏览器进程并在那里进行处理。 CEF3 Faqs涵盖了此通信,以防您以前无需执行此操作:

  

[...] 如何在浏览器之间发送信息并在CEF3中渲染流程?

     

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

似乎这在Adobe Brackets-Shell(一个使用CEF3的相当流行的开源WebIDE)中是一个非常大的问题 - 他们的guide to V8 extensions非常顺利。

  

每当调用本机函数时,都会调用AppShellExtensionHandler::Execute()。此代码在渲染过程中运行,因此此处只应执行最简单的扩展代码。对于括号,此处仅处理getElapsedMilliseconds()。所有其他调用都通过CefProcessMessage传递给浏览器进程。

此处提及的AppShellExtensionHandler相当于您的AppExtensionHandler。我强烈建议您通过他们的代码进行扩展处理 - 它已经非常优雅地完成了。 公平警告:虽然Brackets.io是一家开源企业,但我与Adobe有着专业的关系。

希望这会有所帮助 - 干杯!

答案 1 :(得分:2)

看一下这篇文章。它就像一个魅力。将我的所有JS解决为原生问题,并使用结构化的param传递方法......它恰好解决了你所遇到的问题......你只需要创建一个用户线程(Task)来处理后台的东西......

JS to native via V8Context - async!

我自己测试了这个并且效果非常好......我没有错过的东西......

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