elixir - 工人在主管中启动后退出
问题描述
我正在尝试在我在 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 并使其工作,但是我们如何启动一个简单的工作人员?为什么主管不再重新启动它?不是无限次,而是有时?它至少应该尝试重新启动并失败。如果有的话,也请提出其他改进。
解决方案
主管希望孩子们回来{: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
这应该这样做。
推荐阅读
- mysql - 无法在 Windows 10 上的 MySQL 8.x 中设置 lower_case_table_names
- javascript - 在应用程序脚本中循环切换语句
- java - 在 Java 中集成 python 脚本
- azure - Microsoft Azure 存储资源管理器 - 加载属性时出错
- mysql - MySQL在两列之间找到缺失的组合
- java - 如何从加权图的文件中编码邻接矩阵
- javascript - Vue2:无效的正则表达式标志
- python - 用 Beautiful Soup 刮掉多页 - 只显示最后一页
- clojure - Clojure 在没有库的情况下读取 TGA
- laravel - 是否可以使用相同的表格将数据提交到不同的表格?