再会,
我有一个gen_server
进程,它会定期执行一些长时间运行的状态更新任务handle_info
:
handle_info(trigger, State) ->
NewState = some_long_running_task(),
erlang:send_after(?LOOP_TIME, self(), trigger),
{noreply, NewState}.
但是,当此类任务运行时,整个服务器将变得无响应,对其的任何调用都将导致整个服务器崩溃:
my_gen_server:status().
** exception exit: {timeout,{gen_server,call,[my_gen_server,status]}}
in function gen_server:call/2
如何避免gen_server的阻塞?
当任何时候调用
my_gen_server:status()
时,结果应该是这样的:{ok, task_active}
最佳答案
在一个单独的过程中执行长期运行的任务。让该进程将其在任务中的进度通知gen_server(也就是说,是否可以跟踪任务的进度),或者让该进程完成任务或失败,但至少将任务的结果告知gen_server。
让gen_server与执行此长时间运行任务的进程链接,并让gen_server知道PID或注册名称,以便在退出信号出现的情况下,可以将重要进程的死亡与其余进程隔离开来。
handle_info(触发状态)->
Pid = spawn_link(?MODULE,some_long_running_task,[State]),
NewState = save_pid(Pid,State),
{noreply,NewState};
handle_info({'EXIT',SomePid,_},State)->
case lookup_pid(State)==的某些
假-> %%其他过程
{noreply,State};
正确->
%%我们的流程已终止
%% 我们现在干什么 ?
%%产生了另一个?
%%多数民众赞成在您做出决定后
....
....
{noreply,State}
结尾;
handle_info({finished,TaskResult},State)->
..... %%更新状态等
erlang:send_after(?LOOP_TIME,self(),trigger),
{noreply,NewState}。
some_long_running_task(ServerState)->
....做工作
....返回结果
关于Erlang gen_server具有长时间运行的任务,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8879177/