2016-04-04 2 views
1

ユーザー入力に反応する簡単なエリクシルプログラムを作成しようとしています。私の問題は、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 

答えて

0

これは働くだろう最小のコードです:

t = Task.async(fn -> IO.gets "What?" end) 
Task.await(t) 

は基本的にあなたがawaitに必要返されたタスク。非同期の詳細についてはこちらをご覧ください:http://elixir-lang.org/docs/stable/elixir/Task.html#await/2

+0

urヘルプと私の恐ろしい綴りを訂正してくれてありがとう:) – Kasuyakema

5

ilixirでは、ioを扱うプロセスは常に1つあります。プロセスの1つで何かを印刷すると、stdoutに直接書き込むことはありません。それは "グループリーダー"と呼ばれるプロセスにメッセージを送信します。多くのプロセスは、あなたがこのように混ぜたメッセージを見ることはできません同時に書き込む場合でも:

This is This is message one 
message two 

あなたは常にクリーンな出力を取得します:入力の場合は

This is message one 
This is message two 

を、唯一の存在することができ1つのプロセスがstdinから読み込みます。 iexセッションを実行している場合は、これがシェルプロセスです。他のプロセスがstdinから読み込みたい場合、iexがstdinを制御するまで辛抱強く待ちます。

Task.awaitに電話すると、その機能が魔法のように機能します。それは、プロセスを開始するのを待っているからではありません。 Awaitreceiveと呼ばれ、メッセージが到着するまでそれを呼び出すプロセスを一時停止します。シェルはstdinを放棄し、他のプロセスが使用できるようになり、プロンプトが表示されます。

デフォルトでは、結果が5秒間待つため、すばやくする必要があります。

これらの問題はすべて、対話セッションを実行しているためです。あなたが正常にそれを実行する場合、物事はちょうど動作する必要があります。

result = Task.await(t, :infinity) 

これは公式のTaskドキュメントに記載されていませんが、ほぼすべてのOTPのタイムアウトが原子として無限大を渡すと慣習を尊重:タスクを待っているとき、あなたはこのように無限のタイムアウトを指定することができます。

+0

あなたが正しい方向に私を指して助けてくれたウルのために非常にmutchをありがとう。プログラムの私のタスクは監視ツリーの下で生成されているので、私はTask.awaitを使うことはできないと思うが、私は最初のプロセスを中断することによって解決することができた:timer.sleep(:無限大) – Kasuyakema

関連する問題