由于erlang超时,如何触发handle_info?

Ber*_*ian 2 erlang timeout erlang-otp server

我正在使用 gen_server 行为并试图了解如何handle_info/2从 a 中timeout发生的事件触发handle_call

-module(server).
-export([init/1,handle_call/3,handle_info/2,terminate/2).
-export([start/0,stop/0]).

init(Data)->
    {ok,33}.
start()->
   gen_server:start_link(?MODULE,?MODULE,[]).
stop(Pid)->
   gen_server:stop(Pid).

handle_call(Request,From,State)->
     Return={reply,State,State,5000},
     Return.

handle_info(Request,State)->
    {stop,Reason,State}.

terminate(Reason,State)->
    {ok,S}=file:file_open("D:/Erlang/Supervisor/err.txt",[read,write]),
    io:format(S,"~s~n",[Reason]),
    ok.
Run Code Online (Sandbox Code Playgroud)

我想做的事

我期待,如果我启动服务器并不会使用gen_server:call/25秒(在我的情况),那么handle_info将被称为,这反过来问题stop并进而呼吁terminate。我看到它不会以这种方式发生,事实上handle_info根本没有被调用。

在举例说明如,我看到timeout被设置在返回init/1

我可以推断的是,它handle_info只有当我初始化服务器和问题没有被触发(也没有cast,也没有callN秒)。如果这样,为什么我可以提供Timeoutreturn两个handle_cast / 2handle_call / 3

更新

我试图获得以下功能:

  1. 如果没有callX秒内发出触发handle_info/2
  2. 如果没有castY秒内发出触发handle_info/2

我认为可以在returnofhandle_call和 中设置此超时handle_cast

{reply,Reply,State,X} //for call
{noreply,State,Y}   //for cast
Run Code Online (Sandbox Code Playgroud)

如果没有,这些超时是returns什么时候触发的?

Ale*_*kin 6

要从gen_server:handle_call/3回调启动超时处理,必须首先调用此回调。您的Return={reply,State,State,5000},根本没有被执行。

相反,如果你想“启动服务器并且不会使用gen_server:call/25 秒然后handle_info/2会被调用”,你可能会{ok,State,Timeout}gen_server:init/1回调中返回元组。

init(Data)->
    {ok,33,5000}.
Run Code Online (Sandbox Code Playgroud)

您不能为不同的调用和转换设置不同的超时。正如阿列克谢·罗曼诺夫 (Alexey Romanov) 在评论中所说,

为不同类型的消息设置不同的超时并不是任何gen_*行为都会做的事情,必须通过将它们保持在状态内来模拟。


如果{reply,State,Timeout}从任何handle_call/3/返回元组handle_cast/2,则如果此进程的邮箱在 之后为空,则会触发超时Timeout

  • 我认为这不适用于他的要求(如果我理解正确的话)。相反,效果将是根据稍后处理“call”和“cast”中的哪一个来使用超时之一。任何“gen_*”行为都不会为不同类型的消息设置不同的超时,并且必须通过将它们维持在内部状态来模拟。 (2认同)