Lua子进程返回的输出

在lua中工作,我有一个键值对表

local fmtsToRun = {
  name = function()
    return configSubTable
  end
}

这个表可能包含一项或多项。我需要循环遍历每一个表项,并运行一个子进程(通过一些libuv的C绑定)。

使用普通的for循环,libuv的子进程结果会在循环结束后返回,导致出现无序的情况。结果可能是这样子的:

  • 循环开始
  • 表项1
  • 任务1开始
  • 表项2
  • 任务2开始
  • 循环结束
  • 任务1返回
  • 任务2返回

我需要的是这样子的:

  • 循环开始
  • 表项1
  • 任务1开始
  • 任务1返回
  • 表项2
  • 任务2开始
  • 任务2返回
  • 循环结束

我也尝试着编写自己的pairs()并使用协程来处理回调


for fmt, output in jobIterator(fmtsToRun) do
  print('finished running', output)
end

  local function jobIterator(tbl)
    return coroutine.wrap(function()
      local fmtConf, fmtName
      fmtName, fmtConf = next(tbl, fmtName)
      if nil~=fmtConf then
          local conf = fmtConf()
          local output = nil
          -- 来自Libuv库的封装工具
          local job = Job:new({
              cmd = conf.cmd,
              args = conf.args,
              on_stdout = onStdout, -- 处理输出
              on_stderr = onStderr, -- 处理错误
              on_exit = function()
                coroutine.yield(fmtName, output)
              end
          })
          job.send(conf.data)
      end
    end)
  end

这会导致出现错误信息。

跨越C调用边界尝试进行yield

等待job完成并继续循环,同时保持正确的顺序是什么样的“正确”的方式?

点赞
用户2055617
用户2055617
更好的选择是手动控制流程,并递归调用一个函数逐个遍历表格。

local runner = {} for _, output in pairs(fmtsToRun) do table.insert(runner, output) end jobIterator(runner)

local function jobIterator(tbl) local F = {} function F.step() if #tbl == 0 then return end local current = table.remove(tbl, 1) F.run(current) end

function F.run(conf) local output = nil -- Libuv 库的包装器工具 local job = Job:new( { cmd = conf.cmd, args = conf.args, on_stdout = onStdout, -- 处理输出 on_stderr = onStderr, -- 处理任何错误 on_exit = function() -- 处理输出 print(output) F.step() end } ) job.send(conf.data) end

F.step() end

```

2020-10-31 15:49:21