Node.js C ++插件:线程

我正在为Node.js(wxWidgets)编写一个GUI插件,我想在自己的线程中运行GUI循环,因为我不认为将它与Node的主线程和事件循环合并是一个好主意。

不过,我不知道如何创build一个新的线程。 我得到它与uv_queue_work()运行。 但是它不会为GUI创build独占线程,而是使用Node的线程池。 这可能是一个坏主意,因为工作人员将在整个运行期间停留。 (不知道这个)

我也可以使用wxWidgets的wxThread ,也可以。 我在libuv git master中find了一个新的函数uv_thread_create 。 不知道如何使用,因为没有描述,除此之外它还没有在Node.js stable build中可用。

我的问题:什么是“标准”的方式来创build一个multithreading的Node.js插件,如果有的话? 我查看了其他项目,但只能find使用libuv的短期工作线程。

答案是,您通常需要使用由Nodejspipe理的后台线程,将您的工作提交给uv事件队列,然后让nodejs担心如何创build和pipe理线程。

下面是node.js v0.10手册中缺less的样板例子。

 struct Baton { // we need this structure to interact with the uv // the uv_work_t must be the initial element and should store // the callback function to be useful, but the rest // is user defined depending on what is needed to actually do the work. uv_work_t request; v8::Persistent<v8::Function> callback; // Add more elements to the structure as needed int countdown; }; static void AsyncTestWork (uv_work_t* req); static void AsyncTestAfter(uv_work_t* req,int status); static Handle<Value> AsyncTestPrep(const Arguments& args) { HandleScope scope; if (args.Length() != 1) { ThrowException(Exception::TypeError(String::New("Wrong number of arguments -- needs (callback)"))); return scope.Close(Undefined()); } if (!args[0]->IsFunction()) { ThrowException(Exception::TypeError(String::New("Wrong type of arguments -- needs (callback)"))); return scope.Close(Undefined()); } v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[0]); Baton* baton = new Baton(); baton->request.data = baton; baton->callback = v8::Persistent<v8::Function>::New(callback); baton->countdown = 3; uv_queue_work(uv_default_loop(), &baton->request, AsyncTestWork, AsyncTestAfter); return scope.Close(v8::Undefined()); } static void AsyncTestWork (uv_work_t* req) { // This method will run in a seperate thread where you can do // your blocking background work. // In this function, you cannot under any circumstances access any V8/node js // valiables -- all data and memory needed, MUSt be in the Baton structure Baton* baton = static_cast<Baton*>(req->data); sleep(6); // some fictional work, delaying the return.... baton->countdown -= 1; // my actual work in this } static void AsyncTestAfter(uv_work_t* req,int status) { // This is what is called after the 'Work' is done, you can now move any data from // Baton to the V8/Nodejs space and invoke call back functions Baton* baton = static_cast<Baton*>(req->data); v8::Handle<v8::Value> argv1[] = { v8::Null(), Number::New(baton->countdown) }; v8::Handle<v8::Value> argv2[] = { v8::Null(), Number::New(23) }; v8::TryCatch try_catch; // Call back to the JS function, you can make as many/few callbacks // as you need, they just go on the event loop queue for now. // Note: that it is mostly customary to call the callback // function just (exactly) which is probably what you want // to do to avoid confusing your users if you make a public api baton->callback->Call(v8::Context::GetCurrent()->Global(), 2, argv1); baton->callback->Call(v8::Context::GetCurrent()->Global(), 2, argv2); if (try_catch.HasCaught()) { node::FatalException(try_catch); } if (baton->countdown > 0) { // resubmit the worker for yet more work uv_queue_work(uv_default_loop(), &baton->request, AsyncTestWork, AsyncTestAfter); } else { // we are finished, clean up and be done baton->callback.Dispose(); delete baton; } } void init(Handle<Object> exports) { exports->Set(String::NewSymbol("myAsyncTestFunction"), FunctionTemplate::New(AsyncTestPrep)->GetFunction()); }