Elixir 正确等待进程完成
目前我有这样的想法:Elixir 正确等待进程完成,elixir,Elixir,目前我有这样的想法: ref = Process.monitor(worker) receive do {:DOWN, ^ref, :process, ^worker, :normal} -> IO.puts("Normal exit from #{inspect(worker)}") {:DOWN, ^ref, :process, ^worker, msg} -> IO.puts("Received :DOWN from #{inspect(worker
ref = Process.monitor(worker)
receive do
{:DOWN, ^ref, :process, ^worker, :normal} ->
IO.puts("Normal exit from #{inspect(worker)}")
{:DOWN, ^ref, :process, ^worker, msg} ->
IO.puts("Received :DOWN from #{inspect(worker)}")
end
这个工作者有一个start_链接,它向使用者发送数据流,所有这些都发生在一个mix任务中,因此如果我不添加receive do,一旦mix消失,它也会终止子进程,就像我从iex-S mix shell运行它一样
flow
... some producer consumer in the middle
|> Flow.into_specs(consumer)
问题是,当流为空(是一个有限流)时,工作者似乎不会死亡,接收不会被触发,有没有其他方法来实现这一点
编辑:
我甚至不需要receive do
defmodule Mix.Tasks.Stuff do
def run([]) do
{:ok, worker} = Worker.start_link([])
end
end
defmodule Worker do
def start_link([]) do
Enum.map([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], fn number ->
IO.puts "COUNTING"
Process.sleep(1000)
IO.puts "-----------"
end)
end
end
但是,当工作者启动一个流时,如果我不使用
receive do
等待,它会在我执行任务时立即消失,因此可能这就是问题所在。根据以下文档:
如果调用process.monitor/1
时进程已停止,则会立即发送:DOWN
消息
也就是说,当流
为空时,receive do
将在消息传递后为:DOWN
消息设置处理程序。为了处理这种情况,应该在开始监视流程之前交换调用并准备消息处理程序
receive do
{:DOWN, ref, :process, ^worker, msg} ->
case [retrieve_ref(), msg] do
[^ref, :normal] ->
IO.puts("Normal exit from #{inspect(worker)}")
[^ref, msg] ->
IO.puts("Received :DOWN from #{inspect(worker)}")
end
end
ref = Process.monitor(worker)
store_ref_somewhere_ets_or_agent_or_whatever(ref)
我假设
store\u ref\u某处\u ets\u或\u agent\u或\u which/1
和相应的retrieve\u ref/0
将很容易实现。当流为空时,它应该立即返回,比您进入receive
的过程要快。你能检查一下进程的进程吗?监视器(工作者)返回的进程吗?ref只是一个pid,工作者是这样启动的;{:好的,worker}=worker.start_link([]),然后ref=Process.monitor(worker)您如何预先定义msg?第4行和第6行中的:normal和:DOWN?模式匹配可以区分这两种模式。顺便说一句,我正在测试它(使用:ets),但它并没有停止进程,我的意思是,退出混合任务,在所有有限流被消耗后它会卡住。实际上,我正在调试这个:接收做某事->需要IEx;IEx.pry结束并且没有到达任何对象,如果流在结束时没有发送任何消息,则不会触发