我正在为节点构建一个本机扩展,其中包括一个长时间运行的操作,该操作完成后会进行回调。
我正在将节点缓冲区传递给调用。它包含要由扩展处理的内容的有效负载。
我应该能够将缓冲区存储在AsyncWorker的构造函数中的持久存储中,并在以后需要时检索它。
这个例子(来自nan测试套件)通常是我代码的基础:https://github.com/nodejs/nan/blob/master/test/cpp/bufferworkerpersistent.cpp
这个测试是有效的,但在HandleOKCallback方法之前它不会对缓冲区做任何事情,这对我来说不是很有趣。我需要在Execute方法期间访问缓冲区。
如果我只是在测试的Execute()方法中添加一行来尝试访问缓冲区,如下所示:
void Execute () {
printf("before GetFromPersistentn");
v8::Local<v8::Value> handle = GetFromPersistent("buffer");
printf("after GetFromPersistentn");
printf("buffer @%llux len %ldn", (uint64_t)node::Buffer::Data(handle), node::Buffer::Length(handle));
Sleep(milliseconds);
}
GetFromPersistent调用出现seg错误。
我的问题是:我缺少什么?我应该不能将持久对象拉入Execute方法吗?如果是,为什么不呢?
好吧,我认为答案是"duh",但对于其他刚刚开始使用Node本机扩展的人来说,我现在了解的是:
由于节点是单个线程,若要不阻塞节点,则长时间运行的任务必须在另一个线程中运行。
Nan使用libuv来管理线程池,以完成您在"Execute"方法中编写的异步工作。
然而,AsyncWorker的构造函数实际上是在节点的线程上运行的,并且HandleOKCallback也计划在Execute完成后在那里运行。
因此,在构造函数和回调设置中访问节点资源是可以的,但由于Execute在另一个线程上运行,这是不可以的,所以它会出错。
因此,对于我的问题(我在AsyncWorker中运行JPEG解码),我将指针和长度从构造函数中的缓冲区中取出,但仍在缓冲区上调用SaveToPersistent,这样在解码比特时它就不会被GCed。