3

我正在为节点构建一个本机扩展,其中包括一个长时间运行的操作,并在完成时进行回调。

我将节点缓冲区传递给调用。它包含扩展要处理的内容的有效负载。

我应该能够将我的缓冲区存储在我的 AsyncWorker 的构造函数中的持久存储中,并在以后需要时检索它。

这个例子(来自 nan 测试套件)是我通常基于我的代码的: https ://github.com/nodejs/nan/blob/master/test/cpp/bufferworkerpersistent.cpp

该测试有效,但在使用 HandleOKCallback 方法之前它不会对缓冲区做任何事情,这对我来说不是很有趣。我需要在 Execute 方法期间访问缓冲区。

如果我只是在测试的 Execute() 方法中添加一行来尝试访问缓冲区,如下所示:

void Execute () {
    printf("before GetFromPersistent\n");
    v8::Local<v8::Value> handle = GetFromPersistent("buffer");
    printf("after GetFromPersistent\n");
    printf("buffer @%llux len %ld\n", (uint64_t)node::Buffer::Data(handle), node::Buffer::Length(handle));
    Sleep(milliseconds);
}

GetFromPersistent 调用出现段错误。

我的问题是:我错过了什么?我是否应该无法将持久对象拉入 Execute 方法?如果是这样,为什么不呢?

4

1 回答 1

4

好的,我认为答案是“duh”,但对于刚开始使用 Node 原生扩展的其他人来说,我现在了解的情况如下:

由于 node 是单线程,如果长时间运行的任务不阻塞 node,它们必须在不同的线程中运行。

Nan 使用 libuv 管理一个线程池来完成你在“Execute”方法中编写的异步工作。

但是,您的 AsyncWorker 的构造函数实际上在节点的线程上运行,并且一旦 Execute 完成,HandleOKCallback 也计划在那里运行。

因此,在构造函数和回调设置中访问节点资源是可以的,但是由于 Execute 在不同的线程上运行,所以它不行,所以它会出现故障。

因此,对于我的问题(我在 AsyncWorker 中运行 JPEG 解码),我将指针和长度从构造函数中的缓冲区中拉出,但仍然在缓冲区上调用 SaveToPersistent,这样它就不会在我的时候被 GCed m 对比特进行解码。

于 2015-12-09T17:37:24.367 回答