[FIXED] Wie können Sie einen Emitter-Callback von einem separaten C++-Thread in einem Addon aufrufen?

Ausgabe

Für den Kontext habe ich mit dieser Frage begonnen. Ich muss den Rückruf für den Emitter in einem anderen Thread aufrufen. Ich habe ein Minimalbeispiel gemacht, aber es schlägt fehl. emit.Call({cb, result});Mein erster Instinkt ist, dass ich ein Problem mit der Lebensdauer envoder der emitFunktion habe.

addon.cpp

#include <napi.h>
#include <iostream>
#include <thread>
#include <memory>
#include <functional>
#include <chrono>

std::shared_ptr<std::thread> thread;
bool running = true;

void generate(Napi::Env& env, Napi::Function& emit)
{
  while(running)
  {
    Napi::Array result = Napi::Array::New(env);

    for(int i = 0; i < 3; ++i)
    {
      result[i] = rand()%100;
    }

    auto cb = Napi::String::New(env, "onFeedData");

    emit.Call({cb, result});

    std::this_thread::sleep_for(std::chrono::seconds(1));
  }
}

Napi::Value Start(const Napi::CallbackInfo& info)
{
  Napi::Env env = info.Env();
  Napi::Function emit = info[0].As<Napi::Function>();

  auto cb = std::bind(generate, env, emit);
  thread = std::make_shared<std::thread>(cb);

  return Napi::String::New(env, "OK");
}

Napi::Value Stop(const Napi::CallbackInfo& info)
{
  Napi::Env env = info.Env();
  Napi::Function emit = info[0].As<Napi::Function>();

  running = false;
  thread->join();

  return Napi::String::New(env, "OK");
}

Napi::Object Init(Napi::Env env, Napi::Object exports)
{
  exports.Set(
      Napi::String::New(env, "Start"),
      Napi::Function::New(env, Start));

  exports.Set(Napi::String::New(env, "Stop"),
      Napi::Function::New(env, Stop));

  return exports;
}

NODE_API_MODULE(addon, Init)

index.js

'use strict'

const EventEmitter = require('events').EventEmitter;
const addon = require('./build/addon.node');

function Main() {
  const emitter = new EventEmitter();

  emitter.on('onFeedData', (evt) => {
    console.log(evt);
  })

  setTimeout(() => {
    addon.Stop( emitter.emit.bind(emitter) );
  }, 5000);

  addon.Start( emitter.emit.bind(emitter) );
}

Main();

Lösung

Wir können dies erreichen, indem wir die Funktion napi_create_threadsafe_function () verwenden; Eine solche Verwendung wird ausführlich im StackOverflow-Posting How to use napi_threadsafe_function for NodeJS Native Addon erläutert

Hier ist die node.js-Dokumentation für asynchrone Thread-sichere Funktionsaufrufe


Beantwortet von –
Satyan


Antwort geprüft von –
Marilyn (FixError Volunteer)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like