我正在尝试编写一个简单的 Elixir 程序,它能够对用户输入使用react。我的问题是从 stdio 读取似乎无法从任务中进行。如果我的整个想法很愚蠢,请给我一个例子来说明它是如何完成的。我在网上找不到任何内容
我将问题分解为一个简单的示例:
t = Task.async((fn->IO.gets "what?" end))
%Task{owner: #PID<0.65.0>, pid: #PID<0.80.0>, ref: #Reference<0.0.2.135>}
任务已启动:
iex(4)> pid=Map.get(t, :pid)
#PID<0.80.0>
iex(5)> Process.alive? pid
true
并且还活着,但它不会打印到stdio,也不会读取。它没有正常退出或有异常。我也尝试过 IO.read/2。
在我的程序中,任务是用Task.spawn_link/1启动的,但问题是一样的。IO.gets/2和IO.gets/2函数后面的代码没有执行。
主管开始任务:
defmodule Prime do
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
children = [
# Define workers and child supervisors to be supervised
worker(Task, [fn->Prime.IO.communicate(nil) end], restart: :transient),
supervisor(Prime.Test.Supervisor, [])
]
opts = [strategy: :one_for_one, name: Prime.Supervisor]
Supervisor.start_link(children, opts) end end
任务功能:
defmodule Prime.IO do
@doc """
handles communication with the user and user demanded Actions.
"""
def communicate(numTasks) do
case(numTasks) do
nil ->
{numTasks, _} =Integer.parse(IO.gets "This program searches for prime numbers per try and error.\nHow many concurrent Tasks?\n")
Prime.IO.communicate(numTasks)
x when is_number(x) ->
Prime.Test.Server.setTaskNumber(numTasks)
Prime.IO.communicate("waiting")
y when is_bitstring(y) ->
IO.puts(numTasks)
_ ->
Prime.IO.communicate(nil)
end
end
end
最佳答案
在 Elixir 中总是有一个进程处理 io.如果您在某个进程中打印某些内容,它不会直接写入标准输出。它向称为“组长”的进程发送消息。即使许多进程同时写入,您也看不到像这样混合在一起的消息:
This is This is message one
message two
您将始终获得干净的输出:
This is message one
This is message two
在输入的情况下,只能有一个进程从 stdin 读取。如果您正在运行 iex session ,则这是 shell 进程。如果其他进程想要从 stdin 读取数据,它们会耐心等待,直到 iex 放弃对 stdin 的控制。
这就是为什么,如果您调用 Task.await
该函数会神奇地起作用。这不是因为等待启动了该过程。 Await
在后台调用 receive
,它会挂起调用它的进程,直到有消息传入。Shell 放弃 stdin,现在其他进程可以使用它,因此您会看到提示.
默认情况下,await 会等待 5 秒才能得到结果,所以你必须要快。
所有这些问题都只是因为您正在运行交互式 session 。如果你正常运行它,一切都应该正常。当你等待任务时,你可以像这样指定无限超时:
result = Task.await(t, :infinity)
这在官方 Task
文档中没有记录,但几乎所有 OTP 超时都遵循将无穷大作为原子传递的约定。
关于process - 在 Elixir 任务中获取用户输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36407736/