gpt4 book ai didi

erlang - 如何在 Elixir 中等待多个任务?

转载 作者:行者123 更新时间:2023-12-03 01:25:53 24 4
gpt4 key购买 nike

我想同时执行多个任务。在 Javascript 中,我会这样做:

async function cook_an_egg() {}

async function take_shower() {}

async function call_mum() {}

await Promise.all([cook_an_egg(), take_shower(), call_mum()])

如何在 Elixir Task 模块中实现 Promise.all?来自 documentation ,看来你只能 await 1 个任务;在每个任务内定义1个函数;并使用 async_stream 仅将相同的函数应用于多个项目。

最佳答案

适用于 Elixir v1.11.0 及更高版本

Task.await_many正是为了做到这一点而设计的。它正确处理整体超时,并且在面对退出、超时等情况时应该做最不令人惊讶的事情。

tasks = [
Task.async(fn -> cook_an_egg(:medium) end),
Task.async(fn -> take_shower(10) end),
Task.async(fn -> call_mum() end),
]

Task.await_many(tasks)

对于旧版本

Task.await 更可靠的解决方案是 Task.yield_many 。不幸的是,它有点冗长,因为它让我们自己负责处理超时和死任务。如果我们想模仿 async/await 的行为并在出现问题时退出,它将如下所示:

tasks = [
Task.async(fn -> cook_an_egg(:medium) end),
Task.async(fn -> take_shower(10) end),
Task.async(fn -> call_mum() end),
]

Task.yield_many(tasks)
|> Enum.map(fn {task, result} ->
case result do
nil ->
Task.shutdown(task, :brutal_kill)
exit(:timeout)
{:exit, reason} ->
exit(reason)
{:ok, result} ->
result
end
end)

为什么不使用await

使用Task.await可以在简单的情况下工作,但如果你关心超时,你可能会给自己带来麻烦。跨列表的映射按顺序发生,这意味着每个 Task.await 在给出结果之前将阻塞指定的超时时间,此时我们移动到列表中的下一项并阻塞 再次直至完全超时。

我们可以通过创建休眠 1-8 秒的任务列表来演示此行为。默认超时为 5 秒,当直接使用 await 调用时,其中一些任务将被终止,但当我们枚举列表时,情况并非如此:

for ms <- [2_000, 4_000, 6_000] do
Task.async(fn -> Process.sleep(ms); ms end)
end
|> Enum.map(&Task.await/1)

# Blocks for 6 seconds
# => [2000, 4000, 6000]

# Each `await` picks up after the previous one finishes with a fresh 5s timeout.
# Since each one blocks for 2s before finishing, no timeout is triggered
# but the total run time runs over.

# async(2s)--await(2s)-->(2s)
# async(4s) --await(2s)-->(4s)
# async(6s) --await(2s)-->(6s)

如果我们修改它以使用Task.yield_many,我们可以获得所需的行为:

for ms <- [2_000, 4_000, 6_000] do
Task.async(fn -> Process.sleep(ms); ms end)
end
|> Task.yield_many(5000)
|> Enum.map(fn {t, res} -> res || Task.shutdown(t, :brutal_kill) end)

# Blocks for 5 seconds
# => [{:ok, 2000}, {:ok, 4000}, nil]

关于erlang - 如何在 Elixir 中等待多个任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42330425/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com