Erlang里,如果某个消息迟迟不来, 那么receive有可能进入无限的等待中(比如发送消息的进程crash了)。为了避免这种情况, 可以在receive语句中加入一个超时处理,语法是:
- receive
- Pattern1 [when Guard1] ->
- Expressions1;
- Pattern2 [when Guard2] ->
- Expressions2;
- ...
- after Time ->
- Expressions
- end
在进入receive等待后,如果在Time规定的时间内没有收到消息,则进程停止等待,进入Expressions进行求值。
利用超时实现一个计时器
- -module(stimer).
- -export([start/2, cancel/1]).
- start(Time, Fun) -> spawn(fun() -> timer(Time, Fun) end).
- cancel(Pid) -> Pid ! cancel.
- timer(Time, Fun) ->
- receive
- cancel ->
- void
- after Time ->
- Fun(),
- timer(Time, Fun)
- end.
flush_buffer()清空当前进程的邮箱:
- flush_buffer() ->
- receive
- AnyMessage ->
- flush_buffer()
- after 0 ->
- true
- end.
只要邮箱中还有消息,第一个消息会被匹配到(未绑定变量AnyMessage会匹配到任何消息,在这里就是第一
个消息),然后flush_buffer会再次被调用,但是如果邮箱已经为空了,那么函数会从超时子句中返回。
消息的优先级也可以通过使用0作为超时长度来实现:
- priority_receive() ->
- receive
- interrupt ->
- interrupt
- after 0 ->
- receive
- AnyMessage ->
- AnyMessage
- end
- en
函数priority_receive会返回邮箱中第一个消息,除非有消息interrupt发送到了邮箱中,此时将返
回interrupt。通过首先使用超时时长0来调用receive去匹配interrupt,我们可以检查邮箱中是否已经有了
这个消息。如果是,我们就返回它,否则,我们再通过模式AnyMessage去调用receive,这将选中邮箱中的
第一条消息。
超时报警程序:
- -module(mytimer).
- -export([start/0, timeout/2, cancel/1, timer/3]).
- start() ->
- %io:format("~w", [self()]),
- timeout(1000,warning),
- receive
- Alarm->
- io:format("~w~n", [Alarm])
- end.
- timeout(Time, Alarm) ->
- spawn(mytimer, timer, [self(), Time, Alarm]).
- cancel(Timer) ->
- Timer ! {self(), cancel}.
- timer(Pid, Time, Alarm) ->
- io:format("~w~n", [Pid]),
- receive
- {Pid, cancel} ->
- true
- after Time ->
- io:format("~w", [Pid]),
- Pid ! Alarm
- end.
阅读(2147) | 评论(0) | 转发(0) |