如何在gen_statem中从state_timeout正常退出?通常,对于gen_statem,我可以从状态函数返回“ stop”或{stop,Reason},statem将终止。但是,如果我使用状态超时方法,则从init返回:
{确定,州名,州,{州超时,2000,超时}}
在2000年之后调用handle_event(state_timeout,timeout,StateName,State)方法。从此返回“ stop”会产生错误……:
代码:
handle_event(状态超时,超时,状态名称,状态)->
lager:warning(“设备超时:状态中的〜p:〜p”, [State#state.uuid,StateName]),
{stop,timeout};
错误:
14:29:56.992 [警告] <0.916.0> handle_event(299):超时 设备:状态未定义:init_auth 14:29:56.992 [错误] <0.767.0> 未定义(未定义):已退出大型事件处理程序error_logger_lager_h 原因为{'EXIT',{{badmatch,[module,{state_timeout,timeout
我可以从该函数返回什么以正常退出?能用state_timeout完成吗?如果这是一个明显的问题,请指出正确的方向。这里的文档:http://erlang.org/doc/man/gen_statem.html#type-transition_option似乎没有提到state_timeout的任何返回。似乎我可以指定“下一个状态”,但是退出似乎没有定义
感谢您的帮助!
答案 0 :(得分:0)
系统生成错误,因为与停止消息相关的原因不是// Point(specify location of x, specify location of y)
// with object initializer
var frmUsers = new FrmUsers
{
StartPosition = FormStartPosition.Manual,
Location = new Point(0, 0)
};
// or
var frmUsers = new FrmUsers();
frmUsers.StartPosition = FormStartPosition.Manual;
frmUsers.Location = new Point(0, 0);
。
在这个小例子中,状态机在达到20个超时条件后“正常”退出:
normal
在作品中:
-module (statem).
-behaviour(gen_statem).
-export ([start_link/0]).
-export([init/1, callback_mode/0, terminate/3, code_change/4,handle_event/4]).
start_link() ->
gen_statem:start_link({local,?MODULE}, ?MODULE, [], []).
init([]) ->
{ok, state1, #{info => 0, call => 0 , cast => 0, timeout => 0},[{timeout, 2000, timeout_event}]}.
callback_mode() ->
handle_event_function.
handle_event(timeout,_EventContent,_State,#{timeout := 20}) ->
io:format("max timeout count reached~n"),
{stop, normal};
handle_event(EventType,EventContent,State,Data) ->
io:format("EtventType : ~p~nEventContent : ~p~nState : ~p~nData : ~p~n", [EventType,EventContent,State,Data]),
NewData = process_event(EventType,EventContent,State,Data),
{next_state, State, NewData,[{timeout, 2000, timeout_event}]}.
terminate(_Reason, _State, _Data) ->
ok.
code_change(_Vsn, State, Data, _Extra) ->
{ok, State, Data}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
process_event(info,_EventContent,_State,Data) ->
maps:update(info, maps:get(info, Data)+1, Data);
process_event(cast,_EventContent,_State,Data) ->
maps:update(cast, maps:get(cast, Data)+1, Data);
process_event(timeout,_EventContent,_State,Data) ->
maps:update(timeout, maps:get(timeout, Data)+1, Data);
process_event({call,From},EventContent,_State,Data) ->
gen_statem:reply(From, {got,EventContent}),
maps:update(call, maps:get(call, Data)+1, Data).
{EDIT]
它与state_timeout语法的工作原理相同(我并没有花太多时间去理解它们的区别)
您的代码段中存在语法错误,操作必须包含在列表中(即使只有一个操作)。我尝试了此修改后的代码,它可以正常工作:
74> c(statem).
{ok,statem}
75> {ok,Pid} = statem:start_link().
{ok,<0.197.0>}
EtventType : timeout
EventContent : timeout_event
State : state1
Data : #{call => 0,cast => 0,info => 0,timeout => 0}
EtventType : timeout
EventContent : timeout_event
State : state1
Data : #{call => 0,cast => 0,info => 0,timeout => 1}
76> Pid ! hello.
EtventType : info
EventContent : hello
State : state1
Data : #{call => 0,cast => 0,info => 0,timeout => 2}
hello
EtventType : timeout
EventContent : timeout_event
State : state1
Data : #{call => 0,cast => 0,info => 1,timeout => 2}
EtventType : timeout
EventContent : timeout_event
State : state1
Data : #{call => 0,cast => 0,info => 1,timeout => 3}
77> gen_statem:cast(Pid,cast_msg).
EtventType : cast
EventContent : cast_msg
State : state1
Data : #{call => 0,cast => 0,info => 1,timeout => 4}
ok
...
80> gen_statem:call(Pid,call_msg).
EtventType : {call,{<0.190.0>,#Ref<0.571135265.1570766849.45359>}}
EventContent : call_msg
State : state1
Data : #{call => 0,cast => 3,info => 1,timeout => 17}
{got,call_msg}
EtventType : timeout
EventContent : timeout_event
State : state1
Data : #{call => 1,cast => 3,info => 1,timeout => 17}
...
EtventType : timeout
EventContent : timeout_event
State : state1
Data : #{call => 2,cast => 4,info => 1,timeout => 19}
max timeout count reached
84>