【问题标题】:How does Enum.map works with Task.await?Enum.map 如何与 Task.await 一起工作?
【发布时间】:2017-02-21 05:17:41
【问题描述】:

Elixir Enum.map([Task.t], &Task.await) 是如何工作的?

async_1 = Task.async(fn ->
  IO.inspect("done async 1") 
  1
end)

async_2 = Task.async(fn ->
  IO.inspect("done async 2")
  2
end)

results = Enum.map([async_1, async_2], fn(task) ->
  IO.inspect("starting new task")
  IO.inspect(task)
  Task.await(task) 
end)

IO.inspect(results)

从上面的代码中,我得到了 IO 日志:

"starting new task"
"done async 1"
"done async 2"
%Task{pid: #PID<0.51.0>, ref: #Reference<0.0.0.78>}
"starting new task"
%Task{pid: #PID<0.52.0>, ref: #Reference<0.0.0.79>}
[1, 2]
  1. 我希望第二个"starting new task" 出现在"done async 2" 之前。它是如何急切地执行所有异步任务的?
  2. doc,它说await 将“等待任务回复并返回它”。我认为这意味着它将暂停调用者进程,直到从Task 进程发回完成消息。如果是这种情况,它应该在每次 map 迭代中的每次调用 Task.await(Task.t) 时暂停,并且永远不会真正同时执行这些任务。日志证明我的假设是错误的。但哪里错了?

这是我的回复http://elixirplayground.com?gist=f1fa90eadc00441a360d8bc883d64529

【问题讨论】:

    标签: asynchronous concurrency async-await elixir


    【解决方案1】:

    Task.async 不会等到Task.await 运行传递给它的函数;它立即开始运行。这里分配给任务的工作非常小,所以在Enum.map 有机会等待第二个任务时,他们都已经完成了它的执行。

    【讨论】:

      【解决方案2】:

      感谢@Dogbert 的启发。我在 Elixir 中误解了Task.async

      这让我很困惑,因为在 ES7 和 C# 中,async 只是一个关键字,表示该函数将返回 PromiseAsyncableasync 只负责定义“async_function”。 await 做了两件事——执行和等待结果。即

      function async(action: fn): Promise
      function await(async_action: Promise): ?Any { execute_and_wait(async_function) } 
      

      在 Elixir 中,Task.async 将在一个新进程中执行该函数,这类似于start_link。而await只等待执行进程返回结果。

      并不是说设计不合理。但我更希望他们将其称为 async 以外的其他名称,因为它打破了其他通用语言的惯例,因此更难学习?。

      【讨论】:

        猜你喜欢
        • 2018-12-24
        • 2023-02-02
        • 1970-01-01
        • 2017-08-09
        • 2011-10-13
        • 2015-06-07
        • 2018-07-13
        • 2012-06-22
        • 2011-07-20
        相关资源
        最近更新 更多