有没有办法等待演员完全停止?

时间:2017-01-06 10:48:35

标签: c# akka akka.net

据我所知,Akka.Net中的所有操作都是异步的,Context.Stop()只是向actor发送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 ?

我的应用程序创建了actor来处理来自终端的事件。每次连接新终端时,我都会使用终端名称调用Context.Child()来创建新的actor。当终端断开时,我停止了演员。

问题是有时我在断开相同终端后立即收到Connect消息,结果我得到了将要停止的演员。有没有办法检查该演员收到停止消息并将很快停止?

2 个答案:

答案 0 :(得分:1)

您可以使用

  

var shutdown = actor.GracefulStop(TimeSpan.FromSeconds(42));

它返回一个任务,其结果在42秒内确认关闭

<强>更新

但是,如果您想稍后使用相同的名称重新创建actor,您应该在actor的主管中收听Terminated消息。

答案 1 :(得分:0)

我决定完成处理Terminated消息。

收到Disconnect消息并停止演员后,我将其名称保存在ActorsToBeStopped HashSet中,在创建接收Connect消息的新演员之前,我会检查它是否存在。如果是这样,我将此Connect消息保留在字典中,其中actor名称为key,Connect message为value,并在收到相应actor的Terminated消息后处理它。

这样的事情:

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
    }
}

修改

令人遗憾的是,我无法为其编写测试,因为Akka.TestKit即使在停止后也不允许我创建具有相同名称的TestActor

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之后没有停止,但无论如何我不知道如何等待它终止。