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 を使用してもプロセスは停止しません。ただし、プロセスを停止すると登録が解除されます。したがって、ここで 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.

したがって、サーバーを停止するには、動作関数の 1 つから特別なタプルを返す必要があります。詳細については、こちらをご覧ください。もちろん、ビヘイビア関数の 1 つをトリガーするには、 または を使用してサーバーにメッセージを送信する必要がありますgen_server:cast(gen_server:callまたは、メッセージを送信して で処理しますhandle_info)。何を使用するかはあなたの決定です。最後にterminate2(アトムを含むタプルを返すコールバックに関係なく) が呼び出されstop、状態のクリーンアップを行うことができます。

もちろん、terminateコールバックでプロセスを登録解除できますが、プロセスが終了すると、登録解除は自動的に処理されます。

于 2014-10-22T16:39:30.303 に答える