嵌套分叉的正确模式

我有一个有很多孩子的演员,我正在查询它以获得其孩子们的数据汇总。 此操作可能需要几秒钟。

我即将这样做,感觉非常错误。 handle方法由Ask调用。

 public void Handle(Message message) { var children = Context.GetChildren(); var tasks = new List<Task>(); foreach (var child in children) { var t = child.Ask(new Query); tasks.Add(t); } Task.WaitAll(tasks.ToArray()); // Gah! // do some work Sender.Tell(new Response(new Results())); } 

我有一些想法,但想得到一些意见,因为我真的不想重新发明一个20边的车轮。

我担心Sender的引用以及当我最终调用Tell时它会指向什么,因为它是一个静态调用。

我最终使用了Task.WhenAll延续,但仍然不相信它是正确的Akka方式 – 这就是重点。 我可以使它工作,我只想知道最佳实践选项。

一般来说, Ask应仅用于与外部服务的演员进行通信,几乎从不在两个演员之间进行。 它比使用Tell贵很多。 另外一个问题是使用Task.WaitAll实际上阻​​止当前线程直到所有响应都到达,这对性能也Task.WaitAll并且可能最终导致死锁。

类似的线程已在github上讨论过了。

聚合问题的一般解决方案是:

  • 为聚合过程创建单独的actor。
  • 使用actor列表初始化它,它应该从actor中收集数据并记住actor,它将通过收集的结果进行通知。
  • 发送每个演员的请求/查询。
  • 处理每个请求/查询响应,将其聚合在单独的数据结构中,并从等待的actor列表中删除发送者。
  • 一旦没有参与者等待 – 发送结果并停止当前参与者(负责数据聚合的参与者)。
  • 附加ReceiveTimeout机制以防万一,由于某种原因并非所有参与者都能够在合理的时间内响应 – 当超时时间到来时,您可能会返回到目前为止收集的失败或响应列表。

PS:不要使用TypedActor – 它对性能也有害,并且/将会被淘汰。