C ++在自定义线程中创建cef对象

时间:2013-09-30 07:24:35

标签: c++ multithreading chromium-embedded

我想创建一个javascript对象,将其传递给函数回调,如下所示:

void MyClass::ThreadTaskOnSuccess(CefRefPtr<CefV8Value> callback, CefRefPtr<CefV8Context> callbackCtxt)
{
    if (!CefCurrentlyOn(TID_UI))
    {
        // switch to UI thread
        CefPostTask(TID_UI, NewCefRunnableMethod(this, &NewDownloadObject::CreateTempDownloadOnSuccess, callback, callbackCtxt));
        return;
    }
    // String creation works perfect!
    // CefRefPtr<CefV8Value> executionResult = CefV8Value::CreateString("test");

    // "Access violation" will be thrown
    CefRefPtr<CefV8Value> executionResult = CefV8Value::CreateObject(NULL);

    executionResult->SetValue("size", CefV8Value::CreateInt(123), V8_PROPERTY_ATTRIBUTE_NONE);
    executionResult->SetValue("fileName", CefV8Value::CreateString("some name of file"), V8_PROPERTY_ATTRIBUTE_NONE);

    CefV8ValueList args;
    args.push_back(executionResult);
    CefRefPtr<CefV8Value> retval;
    CefRefPtr<CefV8Exception> exception;
    if (callback->ExecuteFunctionWithContext(callbackCtxt, callbackCtxt->GetGlobal(), args, retval, exception, false))
    {
        if (exception.get())
        {
            throw CFdmException(exception->GetMessage().c_str());
        }
        else
        {
            // Execution succeeded.
        }
    }
}

但是CefV8Value :: CreateObject(NULL)总是返回null结果。我想这是因为代码在自定义线程运行,因为某些任务必须在特殊线程中执行。

我是对的吗?如何切换到cef线程与V8引擎一起工作并与之同步?

我错了吗?为什么V8会创建一个空对象?

更新

我添加了UI线程切换。之后我总是在the Hzmy's quiestion中的cef_v8value_create_object中有“访问冲突读取位置”异常。

2 个答案:

答案 0 :(得分:3)

简而言之:您必须仅从有效线程访问V8。

您可能会错过How to use V8 JavaScript integration in client applications维基页面。

  

使用CEF3 WebKit和JS执行在单独的渲染器进程中运行。渲染器进程中的主线程标识为TID_RENDERER,并且必须在此线程上执行所有V8执行。应使用异步回调设计在浏览器和呈现器进程之间进行通信的JS API。有关示例,请参阅http://www.chromium.org/developers/design-documents/extensions/how-the-extension-system-works/api-pattern-design-doc

答案 1 :(得分:1)

chromiumembedded文档包含以下内容:

  

因此,您应该在使用javascript模型执行操作之前切换正确的竞争对手。   如果V8当前不在上下文中,或者您需要检索并存储对上下文的引用,则可以使用两种可用的CefV8Context静态方法之一。 GetCurrentContext()返回当前正在执行JS的帧的上下文。 GetEnteredContext()返回JS执行开始的帧的上下文。例如,如果frame1中的函数调用frame2中的函数,则当前上下文将为frame2,输入的上下文将为frame1。

     

如果V8在上下文中,则只能创建,修改数组,对象和函数,并且在函数的情况下执行。如果V8不在上下文中,则应用程序需要通过调用Enter()来输入上下文,并通过调用Exit()退出上下文。只应使用Enter()和Exit()方法:

     
      
  1. 在现有上下文之外创建V8对象,函数或数组时。例如,在创建JS对象以响应本机菜单回调时。

  2.   
  3. 在当前上下文以外的上下文中创建V8对象,函数或数组时。例如,如果源自frame1的调用需要修改frame2的上下文。

  4.   

这就是为什么我无法创建对象但能够创建js字符串的原因。 你也可以看到the general usage example

以下代码解决了这个问题:

if (callbackCtxt.get() && callbackCtxt->Enter())
{
    CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(NULL);
    // call ExecuteFunctionWithContext and perform other actions

    callbackCtxt->Exit();
}
相关问题