目前我有这样的东西:
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
,它就会在执行任务后立即死亡,所以也许就是问题所在。
答案 0 :(得分:1)
根据Process.monitor/1
上的文档:
如果在调用
root = tix.Tk()
时进程已经死了,则会立即发送Process.monitor/1
消息。
也就是说,当:DOWN
为空时,Flow
为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_ref_somewhere_ets_or_agent_or_whatever/1
易于实现。