在elixir任务中获取用户输入 [英] Getting user input in an elixir Task

查看:135
本文介绍了在elixir任务中获取用户输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个能够对用户输入做出反应的简单elixir程序。我的问题是从stdio读取似乎不适用于任务。如果我的整个想法很愚蠢,请告诉我一个如何完成它的例子。我在网上找不到任何东西

I'm trying to write a simple elixir program that is able to react to user input. My problem is that reading from stdio doesn't seem to work from Tasks. If my whole idea is silly please show me an example on how it's done. I can't find anything in the web

我把问题简化为一个简单的例子:

I broke my problem down to a simple example:

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。

and alive but it doesn't print to stdio nor does it read. It's not exiting normally or with án exception. I tried IO.read/2 too.

在我的程序中,Task以Task.spawn_link / 1启动,但问题是相同的.IO.gets / 2和IO.gets / 2函数后面的代码未执行。

In my program the Task is started with Task.spawn_link/1 but the problem is the same.IO.gets/2 and code following the IO.gets/2 function is not executed.

主管启动任务:

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的进程。如果您在其中一个进程中打印某些内容,则它不会直接写入stdout。它向称为组长的进程发送消息。即使许多进程同时写入,您也看不到这样的消息:

In Elixir there is always one process handling the io. If you print something in one of processes, it doesn't directly write to stdout. It sends a message to a process called "group leader". Even if many processes write at the same time you can't see messages mixed up like this:

This is This is message one
message two

您将始终获得干净的输出:

You will always get clean output:

This is message one
This is message two

如果输入,只能从stdin读取一个进程。如果你正在运行iex session,那就是shell进程。如果其他进程想要从stdin读取,他们会耐心等待,直到iex放弃对stdin的控制。

In case of input, there can be only one process reading from stdin. If you are running iex session, this the shell process. If other processes want to read from stdin, they wait patiently until iex gives up control over stdin.

这就是为什么,如果你调用任务。等待该函数神奇地起作用。这不是因为等待开始这个过程。 Await 在引擎盖下调用 receive ,它会挂起调用它的进程,直到收到消息.Shell放弃了stdin和现在其他进程可以使用它,所以你看到提示符。

That is why, if you call Task.await the function magically works. It is not because await starts the process. Await under the hood calls receive which suspends the process that called it until a message comes in. Shell gives up stdin and now other processes can use it, so you see the prompt.

默认情况下,await等待5秒的结果,所以你必须快速。

By default await waits 5 seconds for results, so you have to be quick.

所有这些问题仅仅是因为您正在运行交互式会话。如果你正常运行,事情就应该有效。当您等待任务时,您可以指定无限超时,如下所示:

All those problems are simply because you are running interactive session. If you run it normally, things should just work. When you are waiting for the task, you can specify infinite timeout like this:

result = Task.await(t, :infinity)

官方任务中没有记录这一点docs,但几乎所有的OTP超时都遵循将无穷大作为原子的惯例。

This is not documented in official Task docs, but almost all OTP timeouts respect the convention with passing infinity as an atom.

这篇关于在elixir任务中获取用户输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆