如何等待用户的输入并继续进行erlang并发编程中的进一步代码?

     2023-03-15     162

关键词:

【中文标题】如何等待用户的输入并继续进行erlang并发编程中的进一步代码?【英文标题】:How to wait for the input from user and proceed with further code in erlang concurrent programming? 【发布时间】:2019-06-24 23:15:55 【问题描述】:

我正在 Erlang 中进行并发编程,我试图在两个用户之间交换消息。因此,我已经硬编码了一组消息,这些消息作为消息从用户 1 一个接一个地发送到另一个用户 2,我正在从键盘读取输入并将该输入作为回复传递给用户 1。但是在执行它时,不接受输入,并且消息传递在没有输入的情况下继续,并在所有进程完成后最后要求输入。

-module(third).
-import(lists,[nth/2]).
-export([start/0,user2/5,user1/3,inp/1]).

inp(P) ->
ok, [S] = io:fread("entry: \n", "~s"),

P ! S.


user2(0, USERID1,_,_,_) ->
USERID1 ! bye,
io:format("finish");

user2(N, USERID1,Mess,Rep,K) ->
USERID1 ! message, self(),Mess,K,
receive
    reply ->

    S=self(),
        spawn(third, inp, [S])
end,
user2(N-1, USERID1,Mess,Rep,K+1).

user1(Mess,Rep,K) ->
receive
        bye ->
            io:format("conversation over");
        message, USERID2,Mess,K ->
            io:format("~p~n",[nth(K,Mess)]),
            USERID2 ! reply,
            user1(Mess,Rep,K+1)
    end.

start() ->
Mess=["HEY","sup","how are you","yhank you","bye"],
USERID1=spawn(third, user1, [Mess,Rep,1]), 
spawn(third, user2, [5,USERID1,Mess,Rep,1]).

我如何等待输入然后传递该消息。 执行启动模块时输出如下 -

1> c(third).
ok,third 
2> third:start().
"HEY"
<0.77.0>
entry: 
"sup"
entry: 
entry: 
"how are you"
entry: 
entry: 
"yhank you"
entry: 
entry: 
"bye"
entry: 
finishentry: 
entry: 
conversation overentry: 

当它提示输入时,它应该等待输入然后继续。

【问题讨论】:

其实这段代码是行不通的。 start() 函数引用了不存在的 Rep 变量 你可以用任何你想要的方式编写erlang代码,但是如果你需要帮助,那么你必须正确地缩进你的代码。而且,你必须给你的变量和函数起有意义的名字。如您所知,erlang 不是初学者的语言。如果你是编程新手,我建议你改用 python。 【参考方案1】:

稍后给出的版本可以按您的预期工作 - 至少我是这么认为的,因为在您的问题和代码中都没有太多评论。

它包含 2 个修改:

    正如 Odobenus 所说,如果生成函数 inp,函数 user2 立即获得 spawn 的返回值,它是 生成的进程,而不是用户输入的字符串。因此用户2 不等待其他任何事情。该过程仍然存在,因此它将 提示“entry:”,等待输入,但不会使用, 字符串一输入就丢失了。 当您生成函数 user2 时,最后一行还有另一个问题。又是开始 函数在获得新的 pid 后立即停止 过程;由于它是由 shell 命令启动的,因此 shell 采用 立即控制io,user2进程永远得不到 用户输入的字符串,因为它将被 shell 解释为命令。

'''

-module(third).

-export([start/0,user2/4,user1/2,inp/1]).

inp(P) ->
    S = io:get_line("entry: \n"),
    P ! S.


user2(0, USERID1,_,_) ->
    USERID1 ! bye,
    io:format("finish");

user2(N, USERID1,Mess,K) ->
    USERID1 ! message, self(),Mess,K,
    io:format("user2 wait for reply~n"),
    receive
        reply ->
            S=self(),
            inp(S)
    end,
    user2(N-1, USERID1,Mess,K+1).

user1(Mess,K) ->
    receive
        bye ->
            io:format("conversation over");
        message, USERID2,Mess,K ->
            io:format("~p~n",[lists:nth(K,Mess)]),
            USERID2 ! reply,
            user1(Mess,K+1)
    end.

start() ->
    Mess=["HEY","sup","how are you","yhank you","bye"],
    USERID1=spawn(third, user1, [Mess,1]),
    user2(5,USERID1,Mess,1).

'''

但是,在您的示例中,两个用户进程并没有真正进行通信:它们不检查消息,并且每次都交换完整的消息集合。我建议你检查一下这个其他版本,默认情况下,在 5 次交流后,用户 1 关闭聊天,但用户 2 可以通过输入消息“再见”来停止聊天。

'''

-module(third).

-export([start/0,user2/1,user1/1]).


user2(USERID1) ->
    S = io:get_line("entry: \n"),
    USERID1 ! message, self(),S,
    io:format("user2 wait for reply~n"),
    maybe_continue_user2(USERID1,S).

maybe_continue_user2(_,"bye\n") ->
    io:format("User2 ends the chat~n");
maybe_continue_user2(USERID1,_) ->
    receive
        reply,"bye" ->
            io:format("bye, close chat~n");
        reply,Mess ->
            io:format("user2 got ~p~n",[Mess]),
            user2(USERID1)
    end.

user1([]) ->
    io:format("User1 ends the chat~n");
user1([H|T]) ->
    receive
        message,_,"bye\n" ->
            io:format("user 1: conversation over~n");
        message, USERID2,Mess ->
            io:format("~p~n",[Mess]),
            USERID2 ! reply,H,
            user1(T)
    end.

start() ->
    Mess=["HEY","sup","how are you","thank you","bye"],
    USERID1=spawn(third, user1, [Mess]),
    user2(USERID1).

'''

用户 2 停止聊天的示例:

9> third:start().
entry:
hi
user2 wait for reply
"hi\n"
user2 got "HEY"
entry:
how are you?
user2 wait for reply
"how are you?\n"
user2 got "sup"
entry:
bye
user2 wait for reply
user 1: conversation over
User2 ends the chat
ok
10>

【讨论】:

【参考方案2】:

看看这是否有帮助:

-module(my).
-compile(export_all).

start() ->
    register(user1, spawn(my, user1, [["Hello!", "How are you?", "Bye"]]) ),
    register(user2, spawn(my, user2, []) ),
    start_finished.

user1([]) ->
    user1, terminated;
user1([String|Strings])->
    timer:sleep(500), %% See discussion below.
    user2 ! String,

    receive
        Reply -> io:format("user1 received: ~s~n", [Reply])
    end,

    user1(Strings).

user2() ->
    receive
        "Bye" -> io:format("Bye~n");
        Msg -> 
            Prompt = io_lib:format("~s~n>>> ", [Msg]),
            Reply = io:get_line(Prompt),
            user1 ! Reply,
            user2()
    end.

在外壳中:

~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3  (abort with ^G)

1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
ok,my

2> my:start().
start_finished
Hello!
>>> Hi there!
user1 received: Hi there!

How are you?
>>> Good, and you?
user1 received: Good, and you?

Bye
3> 

我不确定我为什么需要timer:sleep() 调用,但它可以防止某些类型的竞争条件导致io:get_line() 发生故障。

【讨论】:

【参考方案3】:

从标准输入读取的代码。您在单独的进程中启动它

spawn(third, inp, [S])

每次 user2 进程收到'reply' atom

顺便说一句,用户输入的结果将被发送到 user2 进程并且永远不会使用。

【讨论】:

C#如何等待弹出窗口并选择它进行输入

】C#如何等待弹出窗口并选择它进行输入【英文标题】:C#Howtowaitforapopupwindowandselectitforinput【发布时间】:2011-05-1207:41:06【问题描述】:我基本上是在用C#编写一个专门的宏播放器/记录器。我需要做的一件事是等待一个弹出窗口... 查看详情

Erlang 并发编程

...的名为calculator的Erlang函数。该函数在进程中运行时应该等待接收消息。如果消息是四项元组的形式:Pid,Operand,X,Y,请执行以下操作:如果Operand为add,则向Pid发送一条消息,其中包含X和Y相加的结果。如果操作数是减法,则向Pid... 查看详情

Gtkmm:如何暂停应用程序的执行并等待用户输入?

】Gtkmm:如何暂停应用程序的执行并等待用户输入?【英文标题】:Gtkmm:Howtopausetheexecutionoftheapplicationandwaitforuserinput?【发布时间】:2018-02-0921:11:02【问题描述】:我正在寻找一种方法来暂停应用程序的执行,而不会冻结它,并且... 查看详情

1.erlang/otp平台

...运行时系统的重要属性?什么是函数式编程,如何用Erlang进行函数式编程1.并发:只有同时发生的任务才能算是并发任务,并发不完全是并行 在Erlang中,并发的基本单位是进程。进程拥有自己的工作内存空间和自己的信箱,... 查看详情

如何提高nfs的并发处理能力

参考技术A有什么方法衡量服务器并发处理能力1.吞吐率吞吐率,单位时间里服务器处理的最大请求数,单位req/s从服务器角度,实际并发用户数的可以理解为服务器当前维护的代表不同用户的文件描述符总数,也就是并发连接数... 查看详情

PLSQL 脚本正在等待用户输入

】PLSQL脚本正在等待用户输入【英文标题】:PLSQLScriptiswaitingforuserinput【发布时间】:2014-02-1711:37:24【问题描述】:我正在尝试运行一个PLSQL脚本,但是当我运行脚本时,如果我按下回车,它正在等待用户输入,那么只有脚本会继... 查看详情

添加到相同的php页面并等待用户输入

】添加到相同的php页面并等待用户输入【英文标题】:Addtosamephppageandwaitforusertoinput【发布时间】:2013-05-0523:06:41【问题描述】:我正在尝试从用户那里获取输入,然后当他按下提交时,它将在数据库中进行查询并在表中返回结... 查看详情

并发编程cas

...这时,一个线程是满足不了的,会因资源独占产生过多的等待,因此需要多线程编程。如果使用并发来编写程序,当一个任务阻塞时,程序中的其他任务还可以继续执行,因此这个任务还可以继 查看详情

并发编程系列之什么是并发协同?(代码片段)

...任务的过程。因为任务处理的需要,需控制某些线程等待另外一些线程执行完成任务的某些部分,然后继续执行。2、并发协同实现方式基于synchronized以及Object的waitnotifynotifyAll监视器方法的方式基于Lock以及Condition的awaitsin... 查看详情

并发编程系列之什么是并发协同?(代码片段)

...任务的过程。因为任务处理的需要,需控制某些线程等待另外一些线程执行完成任务的某些部分,然后继续执行。2、并发协同实现方式基于synchronized以及Object的waitnotifynotifyAll监视器方法的方式基于Lock以及Condition的awaitsin... 查看详情

如何在 Java 中等待多个任务完成?

】如何在Java中等待多个任务完成?【英文标题】:HowtowaitforcompletionofmultipletasksinJava?【发布时间】:2016-04-1511:00:24【问题描述】:在Java应用程序中实现并发的正确方法是什么?我知道线程之类的东西,当然,我已经为Java编程10... 查看详情

Erlang 新手 - 并发和消息传递

...它确实拆分并发送接收到的“块”以计算块。只是不知道如何让所有这些过程 查看详情

如何在模态视图中等待用户输入时停止执行

】如何在模态视图中等待用户输入时停止执行【英文标题】:HowtostopexecutionwhilewaitingforuserinputinaModalView【发布时间】:2011-10-1313:33:18【问题描述】:我有一个导航控制器,显示一个TableView和一个带有按钮的工具栏。如果用户按下... 查看详情

无需等待输入即可输入?

】无需等待输入即可输入?【英文标题】:Cinwithoutwaitingforinput?【发布时间】:2015-02-1908:38:42【问题描述】:对于我正在进行的项目,我需要程序能够接收用户的输入,但是当他们输入内容时,程序可以继续循环。例如:while(true... 查看详情

如何不等待 OpenMP 中的其他线程?

】如何不等待OpenMP中的其他线程?【英文标题】:HownottowaitforotherthreadsinOpenMP?【发布时间】:2010-08-0305:16:31【问题描述】:我正在考虑在C++中使用OpenMP进行多线程处理。但我想知道是否有办法告诉一个线程不要等待其他并发线程... 查看详情

java并发编程-countdownlatch

...景  CountDownLatch是并发包中用来控制一个或者多个线程等待其他线程完成操作的并发工具类。现以工作中的一个场景来描述下CountDownLatch的应用,代码如下:/*模拟工作中的一个需求场景:用户会选择多个算法来计算费用, 查看详情

reactor模型基本并发编程模型

...,没有进行区分。这样做存在一个很大的问题是,必须要等待某个Task处理完成之后,才能接受处理下一个Task。而通常情况下,任务的处理过程会比任务的接受流程慢得多。例如在处理任务的时候,我们可能会需要访问远程数据... 查看详情

java_并发编程面试金典15问

...只有一个用户可以写,为了维护其完整性,您将如何实现它?   锁接口在多线程和并发编程中的最大优点是,它为读写提供了单独的锁,并允许您进行写操作   高性能数据结构,如并发哈希表和条件阻... 查看详情