Использование многопоточного компонента WinRT из WinJS

У меня есть приложение WinJS, которое использует компонент WinRT, написанный на C++/CX. Компонент порождает фоновый поток, который инкапсулирует работу с огромной устаревшей небезопасной библиотекой C++, которая требует, чтобы все вызовы выполнялись из одного потока.

Мне нужно реализовать шаблон производителя / потребителя, где фоновый поток в компоненте является производителем, а поток пользовательского интерфейса в приложении JavaScript является потребителем.

Часть вызова проста, так как JavaScript может вызывать методы компонентов (в потоке пользовательского интерфейса), а код C++ помещает задание в очередь для фонового потока.

Вопрос в обратном вызове: мне нужно опубликовать данные, рассчитанные фоновым потоком C++, в поток пользовательского интерфейса. Я, конечно, могу вернуть IAsyncOperation обратно в JavaScript, но я не хочу, чтобы поток пользовательского интерфейса был заблокирован, пока эта операция ожидает событие из фонового потока.

Какие у меня варианты?

2 ответа

Решение

Решаемые. Посмотрите на раздел: "Чтобы добавить асинхронный метод, который запускает события..." http://msdn.microsoft.com/en-us/library/windows/apps/hh755833.aspx.

Идея состоит в том, что класс компонента объявляет обработчик события (делегат), который может быть установлен в JavaScript. Фоновый поток C++ может инициировать событие в контексте потока пользовательского интерфейса, поэтому обработчик событий JavaScript называется правильным способом.

Конечно, это может быть легко помещено в WinJS.Promise, поэтому код приложения JavaScript не будет знать о наличии компонентов, событий и т. Д.

Если вы реализуете IAsyncOperation в C++/CX на стороне Javascript, это представит обещание. Для выполнения обещания не блокировать поток пользовательского интерфейса вы можете

  • Либо реализуйте вращение работы в асинхронном режиме (например, с использованием потоков) и управляйте обратными вызовами самостоятельно.
  • Используйте библиотеку PPL, которая создает простые обертки вокруг лямда-выражений.

В случае использования PPL вы можете использовать concurrency::create_async для преобразования лямбда-выражения в IAsyncOperation, выполняемый в отдельном потоке, например:

#include <thread>
#include <ppltasks.h>
IAsyncOperation<int64>^ Class1::GetAnswer()
{ 
    return create_async([]() -> int64{
        std::this_thread::sleep_for(std::chrono::seconds(10));
        return 42;
    });
}

Со стороны Javascript вы можете использовать эту IAsyncOperation в качестве обещания - без фактической работы, вешающей поток пользовательского интерфейса:

var nativeObject = new CPPComponent.Class1();
  nativeObject.getAnswer().then(function(value){
    // do something with the result
  });
Другие вопросы по тегам