многопоточность — C ++ создает объект cef в пользовательском потоке

Я пытаюсь создать объект 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) всегда возвращает нулевой результат. Я думаю, это происходит потому, что код бежать в пользовательская тема, для некоторых задач должны быть выполнены в специальной теме.

Я прав? А как перейти на cef thread для работы с движком V8 и синхронизировать с ним?

Я ошибся? И почему V8 создает нулевой объект?

обновленный

Я добавил переключение потоков пользовательского интерфейса. После этого у меня всегда есть исключение «Место чтения нарушения доступа» в cef_v8value_create_object, как в молчание.

2

Решение

Короче говоря: вы должны получить доступ к V8 только из действующего потока.

Вы, вероятно, скучаете Как использовать интеграцию JavaScript V8 в клиентских приложениях вики-страница

С CEF3 выполнение WebKit и JS запускается в отдельном процессе визуализации. Основной поток в процессе рендеринга идентифицирован как TID_RENDERER, и все выполнение V8 должно происходить в этом потоке. API-интерфейсы JS, которые обмениваются данными между процессами браузера и визуализации, должны разрабатываться с использованием асинхронных обратных вызовов. Увидеть http://www.chromium.org/developers/design-documents/extensions/how-the-extension-system-works/api-pattern-design-doc для примера.

3

Другие решения

Chromiumembedded документация содержит следующее:

Таким образом, вы должны включить правильный контекст перед вашими действиями с помощью модели JavaScript.
Если V8 в настоящее время не находится внутри контекста, или если вам нужно получить и сохранить ссылку на контекст, вы можете использовать один из двух доступных статических методов CefV8Context. GetCurrentContext () возвращает контекст для фрейма, который в данный момент выполняет JS. GetEnteredContext () возвращает контекст для фрейма, где началось выполнение JS. Например, если функция в frame1 вызывает функцию в frame2, то текущий контекст будет frame2, а введенный контекст будет frame1.

Массивы, объекты и функции могут создаваться, изменяться и, в случае функций, выполняться, только если V8 находится внутри контекста. Если V8 не находится внутри контекста, то приложение должно войти в контекст, вызвав Enter (), и выйти из контекста, вызвав Exit (). Методы Enter () и Exit () должны использоваться только:

  1. При создании объекта V8, функции или массива вне существующего контекста. Например, при создании объекта JS в ответ на собственный обратный вызов меню.

  2. При создании объекта, функции или массива V8 в контексте, отличном от текущего контекста. Например, если вызов, исходящий из frame1, должен изменить контекст frame2.

Вот почему я не смог создать объект, но смог создать строки js.
Также вы могли видеть общий пример использования.

И следующий код решает проблему:

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

callbackCtxt->Exit();
}
1