据我所知,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消息,结果我得到了将要停止的演员。有没有办法检查该演员收到停止消息并将很快停止?
答案 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
之后没有停止,但无论如何我不知道如何等待它终止。