1

我对nodejs和子进程有点陌生,现在在我的应用程序中遇到了一些麻烦。关于背景的一些事情:我有一个 nodejs-Websocket-Server 工作,可以将 HTML 页面加载到正在连接的任何用户。如果用户按下 HTML 上的按钮,它会向服务器发送一条消息,表明它应该启动图像捕获进程(作为节点中的子进程)。因此,您可以将其与在子进程中运行的某种无限循环进行比较。到目前为止一切顺利,这对我有用。

但是现在,如果用户再次按下按钮,子进程应该停止,因此图像捕获不会继续进行。我的问题是,我不知道如何从主进程停止子进程而不完全杀死它(用户应该能够再次启动循环)。

这是主进程的一个片段(“开始”是真或假,取决于用户是否按下了开始按钮。每次用户点击按钮“开始”改变其状态):

var aCapLive = child.fork(__dirname + "/cp_capture_liveimg_async.js");  //Livebild
if (start) aCapLive.send(start);
else aCapLive.send(start);

这是来自孩子的:

var i = 0;
process.on("message", function(message)
{
    while(message)
    {
        console.log("CP aCapLive received message: Iteration " + i++);
    }
    console.log("CP aCapLive is going to exit now...");
    process.exit();
}

显然这对我不起作用,因为我正在循环中运行并且无法检测到“消息”中的任何变化。如果有人有一些想法,我将非常感激:)

4

2 回答 2

0

正如您所拥有的那样,您的代码永远不会收到超过一条消息,因为它会立即进入无限循环,永远不会将控制权返回给事件循环。该message变量永远不会神奇地改变,并且由于节点是单线程的,因此除非第一条消息评估为假,否则子节点无法退出。

我认为你想要更像这样的东西:

var i = 0;
process.on("message", function(message)
{
    if(message)
    {
        console.log("CP aCapLive received message: Iteration " + i++);
    }
    else
    {
        console.log("CP aCapLive is going to exit now...");
        process.exit();
    }
});

如果你想要一个无限循环,你必须在每次迭代后将控制权返回给事件循环。这将允许新消息进入。示例:

var _message;
var _running = false;
process.on("message", function (message)
{
    _message = message; // update the _message var when a new one comes in
    if (!_running) // this just prevents multiple loops from being started.
    {
        _running = true;
        run();
    }
});

var i = 0;
function run ()
{
    if(_message)
    {
        console.log("CP aCapLive received message: Iteration " + i++);
        setImmediate(run); // <-- this causes an infinite non-blocking loop
    }
    else
    {
        console.log("CP aCapLive is going to exit now...");
        process.exit();
    }
}

如果message每次都一样,那么您真正想要的是这样的切换系统:

var _message = false;
process.on("message", function ()
{
    _message = !_message; // update the _message var when a new one comes in
    if (_message)
        run();
});

var i = 0;
function run ()
{
    if(_message)
    {
        i++;
        if (i % 10000 === 0)
            console.log("CP aCapLive received message: Iteration " + i);
        setImmediate(run); // <-- this causes an infinite non-blocking loop
    }
    else
    {
        console.log("CP aCapLive is going to exit now...");
        process.exit();
    }
}

这是我用来测试它的父进程代码:

var childProcess = require('child_process');

var proc = childProcess.fork('child.js');
proc.send(true);
setTimeout(function () { proc.send(true); }, 4000); // send second message

输出:

CP aCapLive received message: Iteration 10000
CP aCapLive received message: Iteration 20000
CP aCapLive received message: Iteration 30000

... full output omitted for brevity ...

CP aCapLive received message: Iteration 1660000
CP aCapLive received message: Iteration 1670000
CP aCapLive received message: Iteration 1680000
CP aCapLive is going to exit now...
于 2013-07-12T17:03:46.073 回答
0

我做了一些错误修复,所以现在我可以根据需要经常启动和停止循环(将 process.exit() 替换为 clearImmediate(id) 以便可以一次又一次地执行该过程):

var _message;
var _running = false;
var i = 0;

process.on("message", function (start)
{
    _message = start; // update the _message var when a new one comes in
    if (!_running) // this just prevents multiple loops from being started.
    {
        _running = true;
        run();
    }
});


function run ()
{
    if(_message)
    {
        console.log("CP aCapLive received message: Iteration " + i++);
        var id = setImmediate(run); // <-- this causes an infinite non-blocking loop
    }
    else
    {
        console.log("CP aCapLive is going to exit now...");
        _running = false;
        clearImmediate(id);
    }
}
于 2013-07-14T18:45:49.700 回答