Javascript Chromium嵌入式框架中本机函数的后台处理

Javascript Chromium嵌入式框架中本机函数的后台处理,javascript,c++,multithreading,chromium,chromium-embedded,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::OnConte

我正在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;
}
cef设置;
settings.single_process=true;
void应用程序::OnContextCreated(
CefRefPtr浏览器,
CefRefPtr框架,
CefRefPtr(上下文)
{
CoInitializeX(空,Conit_多线程);
//检索上下文的窗口对象。
cefreftr object=context->GetGlobal();
CefRefPtr handler=新AppExtensionHandler(此);
对象->设置值(“execNative”,
CefV8Value::CreateFunction(“execNative”,处理程序),
V8_属性_属性_无);
}
bool AppExtensionHandler::Execute(常量字符串和名称,
CefRefPtr对象,
常量cefv8值列表和参数,
Cefreftr&retval,
(字符串和异常)
{
CefRefPtr browser=CEFW8Context::GetCurrentContext()->GetBrowser();
如果(!browser.get())返回false;
如果(名称==“execNative”){
睡眠(10000);//沉重的过程
CefRefPtr frame=browser->GetMainFrame();
frame->ExecuteJavaScript(L“result(true)”,frame->GetURL(),0);
}
返回true;
}

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

您要做的是将其发送到浏览器进程并在那里进行处理。如果您以前不需要这样做,本手册将涵盖此通信:

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

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

在AdobeShell(一个使用CEF3的相当流行的开源WebIDE)中,这似乎是一个相当大的问题——他们的开发过程非常顺利

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

这里提到的
AppShellExtensionHandler
相当于您的
AppExtensionHandler
。我强烈建议您仔细阅读他们的扩展处理代码——这是非常优雅的。公平的警告:我与Adobe有专业关系,尽管bracts.io是一家开源企业


希望这有帮助-干杯

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

我自己测试过,效果很好除非我遗漏了什么


虽然这篇文章描述了C#但将其翻译成C++应该很简单

谢谢你的详细描述。如果OnProcessMessageReceived中存在大量处理,浏览器将冻结。我将通过使用CreateThread将CefV8Value更改为静态值来解决这个问题。