首页 > 解决方案 > 工人在主管中启动后退出

问题描述

我正在尝试在我在 mix.exs 的应用程序模块中调用的主管中启动以下工作人员

像这样

defmodule AppStarter do
import Supervisor.Spec
def start(_type,_args) do
    children=[
        worker(TPMod1,[],[]),
        worker(TPMod2,[],[])
    ]
    opts=[strategy: :one_for_one, name: HelloVisor]
    Supervisor.start_link(children,opts)
end


end

我的一个模块是 GenServer,另一个我保留了一个简单的监听过程。

defmodule TPMod1 do

def start_link() do
 IO.puts "started TPMod1"
 listen()
end



def listen() do
  receive do
    _ -> :ok
  end
  listen()
end

 def child_spec(opts) do
      %{
        id: __MODULE__,
        start: {__MODULE__, :start_link, []},
        type: :worker,
        restart: :permanent,
        shutdown: 500
      }
    end


end

问题是它卡住了,并且没有启动TPMod2我尝试在TPMod1's中做的工人 2start_link()

def start_link() do
 IO.puts "started TPMod1"
 Task.async(&listen/0)
end

但这给了我这个

**(混合)无法启动应用程序 tproject:AppStarter.start(:normal, []) 返回错误:关闭:无法启动子项:TPMod1 **(EXIT)%Task{owner:#PID<0.143.0> ,pid:#PID<0.144.0>,参考:#Reference<0.2187290957.3420192769.212288>}

我可以使它成为 GenServer 并使其工作,但是我们如何启动一个简单的工作人员?为什么主管不再重新启动它?不是无限次,而是有时?它至少应该尝试重新启动并失败。如果有的话,也请提出其他改进。

标签: elixirgen-servererlang-supervisor

解决方案


主管希望孩子们回来{:ok, pid}:ignore或者{:error, reason}

它挂起是因为当主管start_link在您的工作人员上运行该功能时,它会执行(作为他自己),listen这会设置一个receive块,因此它会卡在那里。当您使用 gen_* 模块start_link和朋友时,它会负责生成、正确返回等。

在您的情况下,您可以切换:

def start_link() do
 IO.puts "started TPMod1"
 listen()
end

至:

def start_link() do
 pid = spawn(__MODULE__, :listen, [])
 {:ok, pid}
end

这应该这样做。


推荐阅读