如何在Elixir或Erlang中使用GenServer实现可重置倒计时器

Cha*_*gwu 6 timer elixir countdown gen-server

我们如何使用GenServer实现可重置倒计时器?

1)在固定的时间之后执行任务,例如每60秒执行一次

2)有一种方法可以在计时器过去之前将倒计时重置为60秒

我已经了解了如何使用Erlang的gen_server定期执行操作?但它并没有完全涵盖在倒计时过去之前休息计时器的方面.

谢谢.

Gaz*_*ler 13

如何在Phoenix框架中每隔几个小时运行一些代码?定义如何定期工作.

要使用它作为基础实现取消,您可以执行以下操作:

defmodule MyApp.Periodically do
  use GenServer

  def start_link() do
    GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
  end

  def reset_timer() do
    GenServer.call(__MODULE__, :reset_timer)
  end

  def init(state) do
    timer = Process.send_after(self(), :work, 60_000)
    {:ok, %{timer: timer}}
  end

  def handle_call(:reset_timer, _from, %{timer: timer}) do
    :timer.cancel(timer)
    timer = Process.send_after(self(), :work, 60_000)
    {:reply, :ok, %{timer: timer})
  end

  def handle_info(:work, state) do
    # Do the work you desire here

    # Start the timer again
    timer = Process.send_after(self(), :work,60_000)

    {:noreply, %{timer: timer}}
  end

  # So that unhanded messages don't error
  def handle_info(_, state) do
    {:ok, state)
  end
end
Run Code Online (Sandbox Code Playgroud)

这样可以保留对计时器的引用,从而可以取消它.每次:work收到消息时,都会创建一个新的计时器并将其存储在GenServer的状态中.

  • 从`Process.send_after(self(),:work,60_000)返回的计时器ref`不能用`:timer.cancel(timer)`取消,因为它返回`{:error,:badarg}`.但是,我可以使用`:erlang.cancel_timer(timer)`.我正在使用Elixir v1.1.1. (4认同)
  • 在 Elixir 1.5+ 中,可以使用 `Process.cancel_timer(timer)` 取消定时器 (2认同)