这是我遇到的一个常见场景,我有两个(或更多)演员异步获取一些数据,然后我需要在他们全部完成后进行操作。
这样做的常见模式是什么?
这是一个简化的例子。
public MasterActor : ReceiveActor
{
public MasterActor()
{
Initialize();
}
public void Initiaize()
{
Receive<DoSomeWork>(_ =>
{
var actor1 = Context.ActorOf(Props.Create(() => new Actor1());
var actor2 = Context.ActorOf(Props.Create(() => new Actor2());
// pretend these actors send responses to their senders
// for sake of example each of these methods take between 1 and 3 seconds
actor1.Tell(new GetActor1Data());
actor2.Tell(new GetActor2Data());
});
Receive<Actor1Response>(m =>
{
//actor 1 has finished it's work
});
Receive<Actor2Response>(m =>
{
//actor 2 has finished it's work
});
}
}
要启动此功能,我会发送MasterActor
一条DoSomeWork
消息。
当我同时拥有Actor1Response
和Actor2Response
时,执行操作的常用方法是什么。
我真的不想在每个接收处理程序中检查逻辑是否完成另一个或类似的事情。我想我正在考虑类似于Task.WaitAll()
方法的东西。
我只是以错误的方式攻击问题吗?我是否需要以不同的方式重写演员?
任何常见的模式或解决方案都很棒。
答案 0 :(得分:5)
通常的解决方案是附加请求和响应消息共享的某种关联ID - 因为actor同步处理消息,这可能是未经检查的int / long计数器。
您只需将相关ID存储在调用者内部的某些数据结构(例如set)中,并在收到响应时从组中删除它的相关ID。 WaitAll
基本上在set为空或超时时结束。
您可以使用Context.SetReceiveTimeout(timeout)
设置超时,这样,演员会在一段时间内没有收到任何消息后向自己发送ReceiveTimeout
方法。
这种行为非常通用,可以很容易地抽象出来。
答案 1 :(得分:2)
最简单的方法是增加一个&#34;投票&#34;当每个孩子回复时,依靠主人。当投票==儿童计数时,您已完成。
您可以对此进行扩展,以便仅计算来自每个孩子的第一条消息,或来自每个孩子的特定消息,但这一切都归结为最终计算。