gpt4 book ai didi

erlang - 生成的 Elixir 进程崩溃后,不会生成其他进程

转载 作者:行者123 更新时间:2023-12-01 11:15:54 24 4
gpt4 key购买 nike

在我的程序中,读取 CSV 文件中的每一行后,会生成一个新进程来下载该图像并将其保存到文件系统:

defmodule Downloader.CLI do
alias Downloader.Parser
alias Downloader.Getter

def main(_args \\ []) do
Enum.map(Parser.run, fn(line) ->
line -> handle_download(line)
end)
end

defp handle_download({ :ok, %{ "image_id" => image_id } }) do
pid = spawn(Getter, :run, [])
send(pid, {self(), image_id})

receive do
:ok -> nil
err -> IO.inspect(err)
end
end
end

如果这个 CSV 文件有 1000 个图像,那么在 VM 中创建了 1000 个不同的 elixir 进程。如果这些进程中只有一个抛出异常,则其他进程不会继续。也就是说,可执行文件不会卡住,但不会下载其他图像。

为什么会这样?如果其他进程彼此独立,为什么它们不能继续执行?我觉得缺少一些简单的东西,但我在其他任何地方都找不到。

最佳答案

问题:receive do 等待一条永远不会到达的消息。

这是逐步发生的事情:

  1. spawn 创建进程 pid
  2. 进程 pid 在向初始进程发送回消息之前崩溃
  3. 初始进程卡在接收函数中:它等待消息。只要没有消息发送,一切都被搁置。 Enum.map 下载后不会启动。

为了说明这个问题,在 iex 中运行以下脚本:

Process.send_after(self(), "Hi Luis", 30000)
receive do
mess -> IO.inspect mess
end

您只会在 30 秒后收到 "Hi Luis",并且在这 30 秒内,您的 iex 将等待消息,因为它是同步的。

解决方案:确保始终发回消息,例如使用 Process.monitor/1Supervisor

defmodule Downloader.CLI do
alias Downloader.Parser
alias Downloader.Getter

def main(_args \\ []) do
Enum.map(Parser.run, fn(line) ->
line -> handle_download(line)
end)
end

defp handle_download({ :ok, %{ "image_id" => image_id } }) do
pid = spawn(Getter, :run, [])
Process.monitor(pid)
send(pid, {self(), image_id})

receive do
:ok -> nil
err -> IO.inspect(err)
end
flush # To avoid having a Down message ending prematurely next download
end
end

关于erlang - 生成的 Elixir 进程崩溃后,不会生成其他进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51371005/

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