“状态”以“无进程”错误终止。有什么建议吗?
根据
Supervisor docs
, the
children
名单:
children = [
{Updates, name: Updates},
{State, name: State}
]
应该是一个列表
child specification
元组,其中子规范具有以下有效键:
子规范包含6个键。前两个是必需的,
其余的是可选的:
:ID
-用于在内部标识子规范的任何术语
管理器;默认为给定的模块。在情况下
冲突:ID值,主管将拒绝初始化和
需要显式ID。此密钥是必需的。
开始
-要调用模块函数参数以启动的元组
子进程。此密钥是必需的。
重新启动
-定义终止的子进程何时应
重新启动(参见下面的__restart values_部分)。这把钥匙是
可选,默认为:永久。
关机
-定义子进程应如何
终止(见下文__shutdown values_一节)。这把钥匙是
可选,如果类型为:worker或:infinity if,则默认为5000。
类型为:主管。
类型
-指定子进程是:worker或
主管。此键是可选的,默认为:worker。
有第六把钥匙,
模块
这是很少改变的。它被设定
根据:Start中的值自动创建。
注意没有
name:
您在子规范中列出的密钥。
然而,
GenServer.start_link()
确实有
姓名:
选项:
start-link/3和start/3都支持genserver注册名称
通过:name选项启动时。注册的名称也会自动
终止时清理。支持的值包括:
原子
-genserver使用process.register/2以给定的名称在本地注册。
{:Global,Type }
-genserver使用:global模块中的函数以给定的术语全局注册。
:通过,模块,术语
-genserver以给定的机制和名称注册。:via选项需要一个导出的模块
注册_name/2,注销_name/1,其中是_name/1和send/2。一
例如:全局模块,它使用这些函数
保留进程及其相关PID的名称列表
在全球范围内可用于elixir节点网络。灵丹妙药
提供本地、分散和可扩展的注册中心
用于本地存储动态生成的名称的注册表。
例如,我们可以在本地启动和注册堆栈服务器
跟随:
# Start the server and register it locally with name:
MyStack {:ok, _} = GenServer.start_link(Stack, [:hello], name: MyStack)
所以,我认为你应该这样做:
def init(_arg) do
children = [
Updates,
State
]
然后在genserver中启动_link()函数:
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
二○○五年
下面是一个完整的例子。在
application.ex
你
能够
指定要注册的名称:
children = [
# Starts a worker by calling: Servers.Worker.start_link(arg)
# {Servers.Worker, arg},
{
Servers.CurrentState, [
init_state_with: [:hello, 10],
name_to_register: Servers.CurrentState
]
},
{
Servers.Updates, [
init_state_with: [:goodbye],
name_to_register: Servers.Updates
]
}
]
那么你
能够
这样定义两个GenServer:
lib/servers/updates.ex:
defmodule Servers.Updates do
use GenServer
def start_link(arg) do
GenServer.start_link(
__MODULE__,
arg[:init_state_with],
name: arg[:name_to_register])
end
## Callbacks
@impl true
def init(state) do
{:ok, state}
end
@impl true
def handle_call(:get_updates, _from, state) do
{:reply, state, state}
end
@impl true
def handle_cast({:push, item}, state) do
{:noreply, [item | state]}
end
##User interface:
def get() do
GenServer.call(__MODULE__, :get_updates)
end
def add(item) do
GenServer.cast(__MODULE__, {:push, item})
end
end
lib/servers/current_state.ex:
defmodule Servers.CurrentState do
use GenServer
def start_link(args) do
GenServer.start_link(
__MODULE__,
args[:init_state_with],
name: args[:name_to_register])
end
## Callbacks
@impl true
def init(state) do
IO.inspect(state, label: "The CurrentState server is starting with state")
{:ok, state}
end
@impl true
def handle_call(:get_state, _from, state) do
state_to_add = Servers.Updates.get()
new_state = state_to_add ++ state
{:reply, new_state, new_state}
end
##User interface:
def get() do
GenServer.call(__MODULE__, :get_state)
end
end
然后,您可以使用以下方法进行测试:
defmodule Servers.Go do
def test() do
IO.inspect("Updates has state: #{inspect Servers.Updates.get()}" )
IO.inspect("CurrentState has state: #{inspect Servers.CurrentState.get()}" )
:ok
end
end
在IEX中:
~/elixir_programs/servers$ iex -S mix
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Compiling 1 file (.ex)
The CurrentState server is starting with state: [:hello, 10]
Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Servers.Go.test()
"Updates has state: [:goodbye]"
"CurrentState has state: [:goodbye, :hello, 10]"
:ok
iex(2)>
(注意,第一行输出与服务器启动消息混合在一起。)
但是,您可以使用
__MODULE__
简化工作:
应用程序
:
children = [
# Starts a worker by calling: Servers.Worker.start_link(arg)
# {Servers.Worker, arg},
{ Servers.CurrentState, [:hello, 10] }
{ Servers.Updates, [:goodbye] }
]
lib/servers/updates.ex
:
defmodule Servers.Updates do
use GenServer
def start_link(arg) do
#arg comes from child specification tuple
#inside the `children` list in application.ex
# | module where the GenServer is defined
# |
# | | send arg to the GenServer's init() function
# V V
GenServer.start_link(__MODULE__, arg, name: __MODULE__)
# ^
# |
# register the specified name for this GenServer
end
## Callbacks
@impl true
def init(state) do
{:ok, state}
end
@impl true
def handle_call(:get_updates, _from, state) do
{:reply, state, state}
end
@impl true
def handle_cast({:push, item}, state) do
{:noreply, [item | state]}
end
## User interface:
def get() do
GenServer.call(__MODULE__, :get_updates)
end
def add(item) do
GenServer.cast(__MODULE__, {:push, item})
end
end
lib/servers/current_state.ex:
defmodule Servers.CurrentState do
use GenServer
def start_link(arg) do
#arg comes from child specification tuple
#inside the `children` list in application.ex
# | module where the GenServer is defined
# |
# | | send arg to the GenServer's init() function
# V V
GenServer.start_link(__MODULE__, arg, name: __MODULE__)
# ^
# |
# register the specified name for this GenServer
end
## Callbacks
@impl true
def init(state) do
IO.inspect(state, label: "The CurrentState server is starting with state")
{:ok, state}
end
@impl true
def handle_call(:get_state, _from, state) do
state_to_add = Servers.Updates.get()
new_state = state_to_add ++ state
{:reply, new_state, new_state}
end
## User interface:
def get() do
GenServer.call(__MODULE__, :get_state)
end
end