正确等待过程完成

时间:2018-08-24 09:30:29

标签: 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)}")
end

那个工作人员有一个start_link,它将数据流发送到使用者,所有这些都发生在混合任务中,因此,如果我不添加接收操作,那么一旦混合消失,它也会杀死子进程,同样就像从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

但是当工作人员启动Flow时,如果我不等receive do,它就会在执行任务后立即死亡,所以也许就是问题所在。

1 个答案:

答案 0 :(得分:1)

根据Process.monitor/1上的文档:

  

如果在调用root = tix.Tk() 时进程已经死了,则会立即发送Process.monitor/1消息。

也就是说,当:DOWN为空时,Flowreceive 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_ref_somewhere_ets_or_agent_or_whatever/1易于实现。