代码之家  ›  专栏  ›  技术社区  ›  simo

如何在genserver中使用task.await?

  •  1
  • simo  · 技术社区  · 6 年前

    我正在尝试如何启动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)
    

    那么,我该如何等待结果呢?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Dogbert    6 年前

    有一种方法:在 :load cast ,返回结果 long_process 作为新的国家。然后添加 call 它只返回当前状态(命名为 :get 下面)。由于genserver按消息发送的顺序顺序处理消息,因此 :获取 呼叫将被阻止,直到上一个 :加载 已经完成。

    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秒多一点的时间。