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]
"starting new task"
出现在"done async 2"
之前。它是如何急切地执行所有异步任务的呢?await
将“等待任务回复并将其返回”。我认为这意味着它将暂停调用者进程,直到从Task
进程发回完成消息。如果是这种情况,它应该在每个Task.await(Task.t)
迭代中的map
的每次调用中暂停,并且从不真正同时执行这些任务。日志证明我的假设是错误的。但哪里错了?这是我的repl http://elixirplayground.com?gist=f1fa90eadc00441a360d8bc883d64529
答案 0 :(得分:4)
Task.async
不等到Task.await
运行传递给它的函数;它立即开始运行。这里给任务的工作量非常小,所以当Enum.map
有机会等待第二个任务时,它们都已经完成了它的执行。
答案 1 :(得分:0)
感谢@Dogbert的启示。我误解了Elixir中的Task.async
。
它使我感到困惑,因为在ES7和C#中,async
只是一个关键字,表示该函数将返回Promise
或Asyncable
。 async
仅限于定义&#34; async_function&#34;。 await
执行两项操作 - 执行并等待结果。即。
function async(action: fn): Promise
function await(async_action: Promise): ?Any { execute_and_wait(async_function) }
在Elixir中,Task.async
将在新进程中执行该函数,该进程类似于start_link
。并且await
仅等待执行过程返回结果。
不是说设计不合理。但是我更希望他们称之为async
以外的东西,因为它打破了其他常用语言的惯例,因此更难以学习。