在我的程序中,在读取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
Run Code Online (Sandbox Code Playgroud)
如果此CSV文件包含1000个图像,则VM中将创建1000个不同的elixir进程.如果这些进程中只有一个抛出异常,则不会继续其他进程.也就是说,可执行文件不会冻结,但不会下载其他图像.
为什么会这样?如果其他进程彼此独立,为什么不能继续执行?我想错过一些简单的东西,但我在其他任何地方都找不到它.
问题:receive do等待永远不会到达的消息.
这是一步一步发生的事情:
spawn 创造过程 pidpid在将消息发送回初始进程之前,进程崩溃Enum.map下载后不会启动.要说明此问题,请在iex中运行以下脚本:
Process.send_after(self(), "Hi Luis", 30000)
receive do
mess -> IO.inspect mess
end
Run Code Online (Sandbox Code Playgroud)
您将"Hi Luis"在30秒后收到,在这30秒内,您的iex将等待一条消息,因为它是同步的.
解决方案:确保始终发回消息,例如使用Process.monitor/1或a Supervisor.
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
123 次 |
| 最近记录: |