嵌套分叉的正确模式

时间:2015-09-06 14:48:39

标签: c# akka.net

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

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

public void Handle(Message message)
{
    var children = Context.GetChildren();
    var tasks = new List<Task<Result>>();

    foreach (var child in children)
    {
        var t = child.Ask<Result>(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方式 - 这就是重点。我可以让它发挥作用,我只想知道最佳实践选择。

1 个答案:

答案 0 :(得分:5)

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

在github上已经讨论过类似的thread

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

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

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