从子线程访问指针

Access a pointer from a child thread

我有一个看起来像这样的结构:

struct Work {
  uv_work_t requst;
  Local<Promise::Resolver> resolver;
};

然后我有了使用 imagemagick 裁剪图像的方法:

void MagickNode::Crop(const FunctionCallbackInfo<Value> &args) {
  // Create a promise
  Local<Promise::Resolver> resolver = v8::Promise::Resolver::New(i.isolate);
  args.GetReturnValue().Set(resolver->GetPromise());

  // Create a worker
  Work *work = new Work();
  work->requst.data = work;
  work->resolver = resolver;

  // Do work
  uv_queue_work(uv_default_loop(), &work->requst, [](uv_work_t *req) {
    // Do the heavy lifting
  }, WorkVoidComplete);
}

流程完成后,我想解决承诺。我在这里做的:

void MagickNode::WorkVoidComplete(uv_work_t *req, int status) {
  // Setup the required items
  Isolate *isolate = Isolate::GetCurrent();
  v8::HandleScope handleScope(isolate);
  Work *work = static_cast<Work *>(req->data);

  // Resolve the promise
  work->resolver->Resolve(Undefined(isolate));
  delete work;
}

问题是,当 work->resolver->Resolve 运行 时,它给出了 分段错误 。我认为这是因为它是在父线程上创建时从线程执行的,因此我无权访问。

我怎样才能访问 运行 那条线?

如果我将该行移动到方法 MagickNode::Crop 的末尾,它 运行 没有错误并且调用了 promise。

你的WorkVoidComplete实际上会在循环线程中被调用。这里的问题是您使用的是 Local<T> 句柄而不是 Persistent<T> 句柄。

MagickNode::Crop 的范围关闭时,释放本地句柄。

将您的结构更改为使用 v8::Persistent<Promise::Resolver> 将解决该问题。请注意,当您使用完持久引用句柄后,必须通过调用 Reset().

手动释放它
class Work {
 public:
  Work(Isolate* i, Local<Promise::Resolver> r)
    : isolate_(i) {
      resolver_.Reset(i, r);
    }

  ~Work() {
    resolver_.Reset();
  }

  inline uv_work_t* request() { return &request_; }
  inline Isolate* isolate() { return isolate_; }
  inline Local<Promise::Resolver> resolver() {
    return resolver_.Get(isolate_);
  }

 private:
  Isolate* isolate_;
  Persistent<Promise::Resolver> resolver_;
  uv_work_t request_;
};

void Something(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();

  Local<Promise::Resolver> resolver =
    v8::Promise::Resolver::New(context).ToLocalChecked();

  Work* work = new Work(isolate, resolver);
  work->request()->data = work;
  uv_queue_work(uv_default_loop(), work->request(), DoWork, WorkComplete);

  args.GetReturnValue().Set(resolver->GetPromise());
}