从子线程访问指针
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());
}
我有一个看起来像这样的结构:
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());
}