代码之家  ›  专栏  ›  技术社区  ›  Dmitry Shkolnik

使用WinJS中的多线程WinRT组件

  •  1
  • Dmitry Shkolnik  · 技术社区  · 13 年前

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

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

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

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

    我有什么选择?

    2 回复  |  直到 13 年前
        1
  •  1
  •   Gergely Orosz    13 年前

    如果您在Javascript端的C++/CX中实现IAsyncOperation,这将暴露 promise 。为了执行承诺而不阻塞UI线程,您可以

    • 要么异步实现工作的旋转(例如使用 threawds)和自己管理回调
    • 使用 PPL library 在lamda周围创建简单的包装 表达。

    在使用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
      });
    
        2
  •  0
  •   Phi Dmitry Shkolnik    5 年前

    解决了的。请看的部分:“添加一个触发事件的异步方法…” https://learn.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应用程序代码就不会知道有组件、事件等。