Вот пример, который демонстрирует, что ответ Wotek Surowka является правильным:
-module(s1).
-behavior(gen_server).
-compile(export_all).
start() ->
gen_server:start_link(
{local, ?MODULE},
?MODULE,
[],
[]
).
init(_Args) ->
Count = 0,
{ok, Count}.
handle_call(_Msg, _From, State) ->
{reply, hello, State}.
handle_cast(_Msg, Count) ->
io:format("Entered handle_cast()...~n"),
self() ! hello,
timer:sleep(10000), % Sleep for 10 seconds
io:format("Returning from handle_cast()...~n"),
{noreply, Count+1}.
handle_info(Msg, Count) ->
io:format("Entered handle_info(), Msg= ~w~n", [Msg]),
io:format("Count in handle_info() is: ~w~n", [Count]),
io:format("Returning from handle_info()...~n"),
{noreply, Count}.
go() ->
spawn(
fun() -> gen_server:cast(?MODULE, "some message") end
),
ok.
В приведенном выше примере handle_cast()
спит в течение 10 секунд, поэтому, если handle_info()
выполняется асинхронно, у него будет много время, чтобы отобразить его вывод, прежде чем handle_cast()
вернулся. Вот результаты в оболочке:
~/erlang_programs/gen_s/1server$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(s1).
s1.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,s1}
2> s1:start().
{ok,<0.71.0>}
3> s1:go().
Entered handle_cast()...
ok <--- return value of go()
Returning from handle_cast()...
Entered handle_info(), Msg= hello
Count in handle_info() is: 1
Returning from handle_info()...
4>
Вывод показывает, что handle_info()
не начинает выполняться, пока не вернется handle_cast()
.
И, если вы добавите несколько операторов печати чтобы отобразить pid
внутри handle_cast()
и handle_info()
, вы увидите, что pid одинаков:
-module(s1).
-behavior(gen_server).
-compile(export_all).
start() ->
gen_server:start_link(
{local, ?MODULE},
?MODULE,
[],
[]
).
init(_Args) ->
Count = 0,
{ok, Count}.
handle_call(_Msg, _From, State) ->
{reply, hello, State}.
handle_cast(_Msg, Count) ->
io:format("Entered handle_cast()...~n"),
Self = self(),
io:format("self() is: ~w~n", [Self]),
Self ! hello,
timer:sleep(10000), % Sleep for 10 seconds
io:format("Returning from handle_cast()...~n"),
{noreply, Count+1}.
handle_info(Msg, Count) ->
io:format("Entered handle_info(), Msg= ~w~n", [Msg]),
io:format("self() is: ~w~n", [self()]),
io:format("Count in handle_info() is: ~w~n", [Count]),
io:format("Returning from handle_info()...~n"),
{noreply, Count}.
go() ->
spawn(
fun() -> gen_server:cast(?MODULE, "some message") end
),
ok.
В оболочке:
1> c(s1).
s1.erl:3: Warning: export_all flag enabled - all functions will be exported
{ok,s1}
2> s1:start().
{ok,<0.71.0>}
3> s1:go().
Entered handle_cast()...
ok <---return value of go()
self() is: <0.71.0>
Returning from handle_cast()...
Entered handle_info(), Msg= hello
self() is: <0.71.0>
Count in handle_info() is: 1
Returning from handle_info()...
4>