9

这是我遇到的一个常见场景,我有两个(或更多)演员异步获取一些数据,然后我需要在他们全部完成后进行操作。

这样做的常见模式是什么?

这是一个简化的例子。

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消息。

当我同时拥有 aActor1Response和 an时,进行操作的常用方法是什么Actor2Response

我真的不想在每个接收处理程序中都有逻辑检查另一个是否完成或类似的事情。我猜我在想什么类似于Task.WaitAll()方法的东西。

我只是以错误的方式解决问题吗?我需要以不同的方式重写演员吗?

任何常见的模式或解决方案都会很棒。

4

2 回答 2

5

常见的解决方案是附加某种由请求和响应消息共享的相关 id - 由于参与者同步处理消息,这可能是未经检查的 int/long 计数器。

您只需将相关 id 存储在调用者内部的某个数据结构(比如说集合)中,当收到响应时,从集合中删除它的相关 id。WaitAll基本上在 set 为空或发生超时时完成。

您可以使用 设置超时Context.SetReceiveTimeout(timeout),这样actorReceiveTimeout在一段时间没有收到任何消息后会向自己发送一个方法。

这种行为非常通用,可以很容易地抽象出来。

于 2015-10-29T10:41:10.077 回答
2

最简单的方法是在每个孩子回复时增加主人的“投票”计数。当投票 == 孩子计数时,你就完成了。

您可以扩展它,以便仅计算来自每个孩子的第一条消息,或来自每个孩子的特定消息,但这一切都归结为最终计数。

于 2015-11-21T23:48:12.803 回答