process - 在 Elixir 任务中获取用户输入

标签 process io task elixir

我正在尝试编写一个简单的 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/

相关文章:

Java 7 - 通过类层次结构流式传输数据

python - 在不加载到内存的情况下查找保存的 numpy 数组(.npy 或 .npz)的形状

c++ - 在 C++ 应用程序的使用中需要对数组、 vector 和映射进行说明

C# 进程终止通知

ios - Xcode 进程启动失败 : Security

java - 操作系统(特别是 Android 的)进程

c++ - 多线程引擎窗口随机减速

c# - 使用任务索引超出范围异常

c# - 我是否应该担心 "This async method lacks ' 等待运算符(operator)并同步运行“警告

android - 获取正在运行的进程列表并终止特定进程