1

我有一个使用 C++/CX 编写的 WinRT 组件的 WinJS 应用程序。组件生成一个后台线程,该线程使用一个庞大的遗留线程不安全 C++ 库来封装工作,这要求所有调用都来自同一个线程。

我需要实现一个生产者/消费者模式,其中组件中的后台线程是生产者,而 JavaScript 应用程序中的 UI 线程是消费者。

调用部分很简单,因为 JavaScript 可以调用组件方法(在 UI 线程中),而 C++ 代码会将作业发布到后台线程的队列中。

问题是回调:我需要将 C++ 后台线程计算的数据发布到 UI 线程中。我当然可以将 IAsyncOperation 返回给 JavaScript,但我不希望 UI 线程在此操作等待来自后台线程的事件时被阻塞。

我有哪些选择?

4

2 回答 2

1

如果您在 Javascript 端的 C++/CX 中实现 IAsyncOperation,这将公开一个promise。为了不阻塞 UI 线程的 promise 的执行,你可以

  • 要么以异步方式实现工作旋转(例如使用 threawds),要么自己管理回调
  • 使用围绕 lamda 表达式创建简单包装器的PPL 库。

在使用 PPL 的情况下,您可以使用 concurrency::create_async 将 lambda 转换为在单独线程上执行的 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 用作承诺 - 无需实际工作挂起 UI 线程:

var nativeObject = new CPPComponent.Class1();
  nativeObject.getAnswer().then(function(value){
    // do something with the result
  });
于 2013-03-07T23:08:47.643 回答
0

解决了。查看https://docs.microsoft.com/en-us/windows/uwp/winrt-components/walkthrough-creating-a-basic-windows的“添加触发事件的异步方法...”部分-runtime-component-in-cpp-and-calling-it-from-javascript-or-csharp

这个想法是组件类声明了一个事件处理程序(委托),它可以在 JavaScript 中设置。C++ 后台线程可以在 UI 线程的上下文中触发事件,因此正确调用 JavaScript 事件处理程序。

当然,这可以很容易地包装到 WinJS.Promise 中,因此 JavaScript 应用程序代码不会知道有组件、事件等。

于 2013-03-20T17:08:21.890 回答