Concurrency 如何在Erlang中对方法应用超时?

Concurrency 如何在Erlang中对方法应用超时?,concurrency,erlang,timeout,Concurrency,Erlang,Timeout,有没有一种方法可以在简单的模块方法调用上应用超时, 例如, my_method(Name)-> timer:sleep(2000), io:format("hello world ~p!~n",[Name]). 我想在上面的方法中添加超时选项,有办法吗?您可以生成函数并等待消息返回。您可以在等待接收时设置超时 my_method(Name)-> YourTimeOut = 10, Self = self(), _Pid = spawn(fun()->

有没有一种方法可以在简单的模块方法调用上应用超时, 例如,

my_method(Name)->
  timer:sleep(2000),
  io:format("hello world ~p!~n",[Name]).

我想在上面的方法中添加超时选项,有办法吗?

您可以生成函数并等待消息返回。您可以在等待接收时设置超时

 my_method(Name)->
  YourTimeOut = 10,
  Self = self(),
  _Pid = spawn(fun()-> 
                  timer:sleep(2000),
                  io:format("hello world ~p!~n",[Name]),
                  Self ! {self(), ok} end),
  receive
    {_PidSpawned, ok} -> ok
  after
     YourTimeOut -> timout
  end.

参见
gen:call/3,4
implementation。它是由

do_call(Process, Label, Request, Timeout) ->
    try erlang:monitor(process, Process) of
    Mref ->
        %% If the monitor/2 call failed to set up a connection to a
        %% remote node, we don't want the '!' operator to attempt
        %% to set up the connection again. (If the monitor/2 call
        %% failed due to an expired timeout, '!' too would probably
        %% have to wait for the timeout to expire.) Therefore,
        %% use erlang:send/3 with the 'noconnect' option so that it
        %% will fail immediately if there is no connection to the
        %% remote node.

        catch erlang:send(Process, {Label, {self(), Mref}, Request},
          [noconnect]),
        receive
        {Mref, Reply} ->
            erlang:demonitor(Mref, [flush]),
            {ok, Reply};
        {'DOWN', Mref, _, _, noconnection} ->
            Node = get_node(Process),
            exit({nodedown, Node});
        {'DOWN', Mref, _, _, Reason} ->
            exit(Reason)
        after Timeout -> %% <-- HERE
            erlang:demonitor(Mref, [flush]),
            exit(timeout)
        end
    catch
    error:_ ->
        %% Node (C/Java?) is not supporting the monitor.
        %% The other possible case -- this node is not distributed
        %% -- should have been handled earlier.
        %% Do the best possible with monitor_node/2.
        %% This code may hang indefinitely if the Process 
        %% does not exist. It is only used for featureweak remote nodes.
        Node = get_node(Process),
        monitor_node(Node, true),
        receive
        {nodedown, Node} -> 
            monitor_node(Node, false),
            exit({nodedown, Node})
        after 0 -> 
            Tag = make_ref(),
            Process ! {Label, {self(), Tag}, Request},
            wait_resp(Node, Tag, Timeout) %% <-- HERE for C/Java nodes
        end
    end.
do_调用(进程、标签、请求、超时)->
试试erlang:的监视器(进程,进程)
Mref->
%%如果monitor/2调用未能建立到的连接
%%远程节点,我们不需要“!”操作员尝试
%%重新设置连接。(如果监视器/2呼叫
%%由于超时过期而失败,“!”也可能
%%必须等待超时过期。)因此,
%%将erlang:send/3与'noconnect'选项一起使用,以便
%%如果没有连接到,将立即失败
%%远程节点。
catch erlang:send(进程,{Label,{self(),Mref},请求},
[无连接],
接收
{Mref,回复}->
erlang:demonitor(Mref,[flush]),
{好的,答复};
{'DOWN',Mref,,,noconnection}->
节点=获取节点(进程),
退出({nodedown,Node});
{'DOWN',Mref,{,{,Reason}->
退出(原因)
超时后->%%
%%节点(C/Java?)不支持监视器。
%%另一种可能的情况——此节点不是分布式的
%%--应该早一点处理。
%%使用monitor_node/2尽可能做到最好。
%%如果进程失败,此代码可能会无限期挂起
%%不存在。它仅用于功能较弱的远程节点。
节点=获取节点(进程),
监控节点(节点,真),
接收
{nodedown,Node}->
监视节点(节点,错误),
退出({nodedown,Node})
0之后->
Tag=make_ref(),
过程{Label,{self(),Tag},Request},

wait_resp(节点、标记、超时)%%“应用/添加超时”是什么意思?就像调用一个函数并在固定的时间内等待回复,如果在该时间内没有响应则返回错误一样?@Dogbert,是的。不管您是使用gen_服务器还是仅仅生成一个简单的进程来完成这项工作,您都需要有两个进程:一个执行调用,另一个等待结果或超时。还有一些事情需要考虑。在超时的情况下,您需要决定如何处理未完成的调用:是终止它,还是让它运行到完成,但删除最终返回值?如果你杀了它,会不会留下一个不一致的状态,以防电话有副作用?