Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir 长生不老药:在主管内部获取流程pid_Elixir - Fatal编程技术网

Elixir 长生不老药:在主管内部获取流程pid

Elixir 长生不老药:在主管内部获取流程pid,elixir,Elixir,我有两种由主管启动的流程:一些工人和一个工人需要向其报告的控制器。为此,他们需要知道控制器的pid 我曾考虑过两种方法,但都不管用 立即开始 其原理是一次启动所有过程,然后检索控制器的pid,然后将其发送给所有工人,以便他们可以开始工作。代码如下所示: defmodule XYZ.MySup do use Supervisor def start_link(opts) do ... end def init(:ok) do children = [ {

我有两种由主管启动的流程:一些工人和一个工人需要向其报告的控制器。为此,他们需要知道控制器的pid

我曾考虑过两种方法,但都不管用

立即开始 其原理是一次启动所有过程,然后检索控制器的pid,然后将其发送给所有工人,以便他们可以开始工作。代码如下所示:

defmodule XYZ.MySup do
  use Supervisor

  def start_link(opts) do
  ...
  end

  def init(:ok) do
    children = [
      {XYZ.Controller, name: :ctrl},

      %{id: XYZ.Worker_1,
        start: {XYZ.Worker,
                :start_link, [[name: :w1, args: {"arg_1"}]]}},

      ... some other workers ...
    ]

    Supervisor.init(children, strategy: :one_for_one)

    ch = Supervisor.which_children(self())
    ...

  end
end
defmodule MyApp.Supervisor do
  use Supervisor

  def start_link do
    # Name your supervisor `MyApp.Supervisor`
    Supervisor.start_link(__MODULE__, [], name: __MODULE__)
  end

  def init([]) do
    children = [
      worker(MyApp.Worker, [])
    ]

    supervise(children, strategy: :simple_one_for_one)
  end
end
Supervisor.which_children(self())
生成进程试图调用自身的错误
**(EXIT)

首先启动控制器 其原理是启动控制器,然后获取其pid,然后以控制器的pid作为参数启动工人(顺便说一句,这是首选方法)

  • 当然,获取控制器的pid也会遇到同样的问题:运行时拒绝调用
    Supervisor.which_children(self))
  • 即使可以解决这一问题,也可以向主管添加一名工人,包括:

    Supervisor.start_child(self(),
      %{id: XYZ.Worker_3,
        start: {XYZ.Worker,
                :start_link, [[name: :w3, args: {"arg_3"}]]}})
    
    失败,出现错误
    **(退出)进程试图调用自身


  • 我做错了什么?

    好的,因此当主管已经在处理消息时,您不能向其发送消息。在这种情况下,它是start_link/init消息。就像Elixir/Erlang中的所有内容一样,所有内容都是一个过程,一次只能处理一条消息。本质上,通过在
    init
    调用中执行此操作,您正在创建一个锁。这是因为,只有在init函数成功退出并且主管是监督树的一部分时,主管才会开始接受消息。这相当于在GenServer自己的handle\u cast/handle\u call回调中调用对GenServer的cast/call

    看起来您还想使用一种
    :简单的一对一
    策略来动态启动工作人员

    接下来,您应该命名您的主管,这样您就可以调用它,而无需获取pid

    最后,您应该将启动功能包装在应用程序定义内的任务中

    就我个人而言,我喜欢这样做:

    defmodule XYZ.MySup do
      use Supervisor
    
      def start_link(opts) do
      ...
      end
    
      def init(:ok) do
        children = [
          {XYZ.Controller, name: :ctrl},
    
          %{id: XYZ.Worker_1,
            start: {XYZ.Worker,
                    :start_link, [[name: :w1, args: {"arg_1"}]]}},
    
          ... some other workers ...
        ]
    
        Supervisor.init(children, strategy: :one_for_one)
    
        ch = Supervisor.which_children(self())
        ...
    
      end
    end
    
    defmodule MyApp.Supervisor do
      use Supervisor
    
      def start_link do
        # Name your supervisor `MyApp.Supervisor`
        Supervisor.start_link(__MODULE__, [], name: __MODULE__)
      end
    
      def init([]) do
        children = [
          worker(MyApp.Worker, [])
        ]
    
        supervise(children, strategy: :simple_one_for_one)
      end
    end
    
    然后在应用程序定义中使用该任务:

    defmodule MyApp.Application do
      use Application
    
      def start(_, _) do
        import Supervisor.Spec, warn: false
    
        children = [
          supervisor(MyApp.WorkerSupervisor, []),
          worker(Task, [&on_boot/0], restart: :temporary)
        ]
    
        Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor)
      end
    
      defp on_boot do
        child_spec = MyApp.Worker.child_spec(args: [_arg1, _arg2, _arg3], name: :w1)
        Supervisor.start_child(MyApp.WorkerSupervisor, child_spec)
        # ... more workers
        :ok
      end
    end
    
    我不完全确定上面的
    child\u spec
    调用,因此您可能需要检查文档:

    然后,您可以通过调用
    supervisor.which_children(MyApp.WorkerSupervisor)
    在应用程序中的任何其他位置获取主管的孩子

    如果要查看生成的监控树,请在iex控制台内使用
    :observer.start()
    ,然后单击
    应用程序
    选项卡,这将非常有用