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_服务器还是仅仅生成一个简单的进程来完成这项工作,您都需要有两个进程:一个执行调用,另一个等待结果或超时。还有一些事情需要考虑。在超时的情况下,您需要决定如何处理未完成的调用:是终止它,还是让它运行到完成,但删除最终返回值?如果你杀了它,会不会留下一个不一致的状态,以防电话有副作用?