【问题标题】:How to use Task.await with GenServer?如何将 Task.await 与 GenServer 一起使用?
【发布时间】:2018-12-24 00:04:33
【问题描述】:

我正在尝试弄清楚如何启动一个 genserver,并等待结果直到它完成。

如何让服务器在退出时返回结果?

例如:

defmodule DistanceMatrix do
  use GenServer

  def start id do
    GenServer.start(__MODULE__, id)
  end

  def load() do
    GenServer.cast({:load})
  end

  def handle_cast({:load}, state) do
    # start long process operation
    long_process
    {:noreply, state}
  end

  def long_process do
    :timer.sleep 2000
    %{result: "Process result.."}
  end

end 


results= ids
|> Enum.map(fn id -> DistanceMatrix.start(id) end)
|> Enum.map(&Task.await/1)
|> Enum.map(fn({:ok, result}) -> 
   result
   end)

那么,我将如何等待并得到结果?

【问题讨论】:

  • 如何将所有cast 更改为call 并调用load 而不是Task.await
  • 我想同时处理所有id,我试过call,但我得到的是顺序而不是并行处理的id。

标签: elixir gen-server


【解决方案1】:

这里有一种方法:在:loadcast中,将long_process的结果作为新状态返回。然后添加一个call,它只返回当前状态(下面命名为:get)。由于 GenServer 按发送顺序依次处理消息,因此 :get 调用将阻塞,直到前一个 :load 完成。

defmodule DistanceMatrix do
  use GenServer

  def start(id) do
    GenServer.start(__MODULE__, id)
  end

  def load(pid) do
    GenServer.cast(pid, {:load})
    pid
  end

  def await(pid), do: GenServer.call(pid, :get)

  def init(id), do: {:ok, id}

  def handle_call(:get, _, state), do: {:reply, state, state}

  def handle_cast({:load}, _state) do
    {:noreply, long_process()}
  end

  def long_process do
    :timer.sleep(2000)
    %{result: "Process result.."}
  end
end

1..10
|> Enum.map(fn id ->
  {:ok, pid} = DistanceMatrix.start(id)
  pid
end)
|> Enum.map(&DistanceMatrix.load/1)
|> Enum.map(&DistanceMatrix.await/1)
|> Enum.map(fn result ->
  IO.inspect(result)
end)

输出:

%{result: "Process result.."}
%{result: "Process result.."}
%{result: "Process result.."}
%{result: "Process result.."}
%{result: "Process result.."}
%{result: "Process result.."}
%{result: "Process result.."}
%{result: "Process result.."}
%{result: "Process result.."}
%{result: "Process result.."}

正如预期的那样,该程序需要 2 秒多一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-14
    • 2019-05-08
    • 2021-01-02
    • 1970-01-01
    • 2023-03-13
    • 2014-09-25
    • 2016-01-30
    • 2015-12-13
    相关资源
    最近更新 更多