2017-01-06 10 views
4

私が知っているように、Akka.Netのすべてのオペレーションは非同期であり、は単にStopメッセージをアクタに送信するだけです。それは、俳優が完全にシャットダウンする前に、ある時間生きていることを意味します。アクタが完全に停止するのを待つ方法はありますか?

Context.Child()の直後にContext.Stop()の後に私が停止した俳優の名前を呼ぶと、私は同じ俳優を迎えます。ここ

var actor = context.Child(actorName); 

if (actor.Equals(ActorRefs.Nobody)) 
{ 
    actor = CreateNewActor(); 
} 

Context.Stop(actor) 
actor = context.Child(actorName); 
// what do we get here, same actor or ActorRefs.Nobody ? 

私のアプリケーションは、端末からのイベントを処理するためにアクターを作成するコード例です。新しい端末が接続されるたびに、端末名を使用してContext.Child()と呼んで新しい俳優を作成します。ターミナルが切断されると、私は俳優を止める。

問題は、同じ端末でDisconnectの直後にConnectメッセージが表示されることがあり、その結果、俳優が停止することがあります。そのアクタが停止メッセージを受信したことを確認する方法はありますか?すぐに停止されますか?

+0

あなたはおよそ次のようになります。DeathWatch 別名 *ライフサイクルの監視*シャットダウンを確認して:私の心に来るGracefulStop –

+0

命題の一つでも[FSM](http://getakka.net/docs/FSM)です。アクターが切断メッセージを受信すると、新しい状態に切り替えて動作を変更します。したがって、Connectメッセージは通常の方法で処理されません。また、Connectメッセージが処理されていないときにアクターが何をすべきかを定義することもできます。 –

答えて

0

私はTerminatedメッセージの処理を完了することに決めました。

Disconnectメッセージを受信し、俳優を停止した後、私はそれがActorsToBeStopped HashSetの中で名前をだし、それが存在する場合Connectメッセージを受信すると、新たな俳優を作成する前に、私はチェックしておきます。もしそうなら、私はこのConnectメッセージを辞書に入れて、アクター名をキーとし、Connectメッセージを値として保持し、対応するアクターの終了メッセージを受け取った後に処理します。このような

何か:Akka.TestKitは私が同じ名前でTestActorを作成することはできませんので、ここで

private readonly Dictionary<string, Connect> postponedConnectMessages = new Dictionary<string, Connect>(); 
private readonly HashSet<string> actorsToBeStopped = new HashSet<string>(); 

// ... 

Receive<Disconnected>(t => 
{ 
    var actor = GetActorByName(t.Name); 
    Context.Stop(actor); 
    actorsToBeStopped.Add(actor.Path.Name); 
}); 

Receive<Connected>(t => 
{ 
    var actor = GetActorByName(t.Name); 

    if (actorsToBeStopped.Contains(actor.Path.Name)) 
    { 
     postponedConnectMessages[actor.Path.Name] = t; 
     return; 
    } 
    // work with actor 
} 

Receive<Terminated>(t => 
{ 
    var deadActorName = t.ActorRef.Path.Name; 
    actorsToBeStopped.Remove(deadActorName); 
    if (postponedConnectMessages.ContainsKey(deadActorName)) 
    { 
     var connectMessage = postponedConnectMessages[deadActorName]; 
     postponedConnectMessages.Remove(deadActorName); 
     var actor = GetActorByName(connectMessage.Name); 
     // we sure we have new actor here 
     // work with actor 
    } 
} 

EDIT

悲しい事は、私はそれのためのテストを書くことができないということです停止した後でも:

public void StopTest() 
{ 
    var t = CreateTestActor("AAAA"); 
    Watch(t); 
    Sys.Stop(t); 
    ExpectTerminated(t, TimeSpan.FromSeconds(10)); 
    var t2 = CreateTestActor("AAAA"); // test fails here 
} 

または、多分停止ではありませんでしたExpectTerminatedの後にペダルを押してください。とにかく、私はそれが終了を待つ方法を知らない。

0

あなたは

するvarシャットダウン= actor.GracefulStop(TimeSpan.FromSeconds(42))を使用することができます。

それは、その結果を確認し、シャットダウン42秒以内に

UPDATE

タスクを返します。しかし、あなたが同じ名前の後に俳優を再作成したい場合場合には、あなたが終了に耳を傾ける必要があります俳優の上司のメッセージ。

+1

私は[ここ](http://getakka.net/docs/Working%20with%20actors#gracefulstop)の注釈を理解しているので、助けてくれません: **警告** _俳優停止し、その名前が登録解除されると、互いに非同期的に発生する別々のイベントになります。したがって、GracefulStop()が返された後でも、まだ使用中の名前が見つかることがあります。適切な登録解除を保証するには、管理している管理者の名前を再利用するだけで、終了したメッセージに応じて、つまり最上位の俳優には返信しないでください._ – bonzaster

+0

ああ、申し訳ありません。私はあなたの元の質問を誤解しました。はい、Grasfullトップはあなたを保証しません、その俳優の名前は登録抹消されます。あなたのケースでは、端末名であなたの俳優を監督する、俳優の終了メッセージを聞くべきです。 –

関連する問題