1

即使我取消注册sts,我生成的进程也没有停止。我怎样才能停止它不使用 gen_server?

start() ->
  case whereis(sts) of
    undefined ->
      PidA = spawn(dist_erlang, init,[]),
      register(sts, PidA),
      {ok,PidA};
    _ ->
      {ok,whereis(sts)}
  end.

stop() ->
   case whereis(sts) of
     undefined -> 
        already_stopped;
     _ ->
        unregister(sts),
        stopped,
  end.
4

2 回答 2

5

使用 unregister 不会停止该过程。但是,停止该进程确实会取消注册它。因此,不要在这里使用取消注册,而是使用erlang:exit/2

stop() ->
    case whereis(sts) of
        undefined -> 
            already_stopped;
        Pid -> 
            exit(Pid, normal), % Use whatever exit reason you want
            stopped
     end.

话虽如此,您确实应该使用 OTP 流程行为(如 gen_server),因为它们使流程管理更加容易。使用 OTP 流程,您可以代替call该流程并告诉它停止,这样当您收到回复时,它已经停止。否则,您的退出消息可能需要一些时间才能通过。

于 2014-10-22T16:18:26.083 回答
1

unregister不会停止进程。它只是删除了进程 id 和给定原子之间的绑定。

您需要记住该stop/0函数是在调用此函数的进程上下文中运行的,而不是在 gen_server 本身。实际上(几乎)与某个进程交互的唯一方法是向它发送消息。所以你可以stop/0像这样实现你的功能:

%% send stop message to `sts` server
stop() ->
  gen_server:cast(sts, stop). 

%% [...]


handle_cast( OtherCastMessages, State) -> 
  %% handel other cast messages ;
  %% [...] ;

%% handle stop message
handle_cast( _Message = stop, State) ->
  {stop, 
   _Reason = normal, 
   State}. % return result that stops server


%% [...]

terminate(_Reason = normal, State) ->
   %% could do some cleanup in this callback
   ok.

因此,要停止服务器,您必须从行为函数之一返回特殊元组。您可以在此处阅读有关此内容的更多信息。当然触发行为功能之一,您必须使用gen_server:castor向您的服务器发送消息gen_server:call(或者只是发送消息并使用 处理它handle_info)。使用什么是您的决定。最后terminate2被调用(无论哪个回调返回带有stop原子的元组),您可以在其中对您的状态进行一些清理。

当然,您可以在terminate回调中注销您的进程,但是当进程终止时,注销会自动处理。

于 2014-10-22T16:39:30.303 回答