如何返回第一个异步任务来完成

Dan*_*_es 7 elixir

我有几个任务,我正在异步运行.根据输入,一个或多个可能会运行很长时间,但只有一个任务将返回:success消息.

slowtask = Task.async(slow())
fasttask = Task.async(fast())
Run Code Online (Sandbox Code Playgroud)

如何捕获上述两个任务中的第一个完成,而不必等待另一个?我已经尝试过了Task.find/2,但是由于它是用enum实现的,所以它似乎在找到ref/message之前等待所有的退出信号.我的另一个想法是对此进行调查Stream.cycle,忽略仍然存在的任务并捕获已退出的任务.看来这种灵丹妙药不喜欢以这种方式进行民意调查.

Jos*_*lim 8

目前还没有简单的方法在Elixir上做到这一点.您最好的选择是,如果您只是在给定进程中等待这些消息,则是这样的:

  defmodule TaskFinder do
    def run do
      task1 = Task.async fn -> :timer.sleep(1000); 1 end
      task2 = Task.async fn -> :timer.sleep(5000); 2 end
      await [task1, task2]
    end

    # Be careful, this will receive all messages sent
    # to this process. It will return the first task
    # reply and the list of tasks that came second.
    def await(tasks) do
      receive do
        message ->
          case Task.find(tasks, message) do
            {reply, task} ->
              {reply, List.delete(tasks, task)}
            nil ->
              await(tasks)
          end
      end
    end
  end

  IO.inspect TaskFinder.run
Run Code Online (Sandbox Code Playgroud)

请注意,您也可以使用此模式在GenServer中生成任务并用于Task.find/2查找匹配的模式.我还将此示例添加到Elixir文档中.

  • 由于所有答案都取决于不推荐使用的“ Task.find”,是否有没有它的想法? (2认同)