2015-09-06 101 views
1

我有一個有很多孩子的演員,我正在查詢它以獲取其子項中的數據聚合。此操作可能需要幾秒鐘。適合嵌套式問題的模式

我正要做到這一點,感覺完全錯了。處理方法由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延續,但仍然不相信這是正確的阿卡方式 - 這是重點。我可以讓它工作,我只想知道最佳實踐方案。

回答

5

一般而言,Ask只能用於與外部服務的演員進行通信,幾乎不會在兩個演員之間進行通信。這比使用Tell貴很多。另外的問題是使用Task.WaitAll,它實際上阻塞當前線程,直到所有響應都到達,這對性能也是不利的,並且可能最終導致死鎖。

類似thread已經在github上討論過。

的聚集問題,一般的解決方法是:

  • 創建聚集過程一個單獨的演員。
  • 使用演員列表進行初始化,它應該從演員收集數據並記住演員,演員將收到結果通知。
  • 發送請求/查詢每個演員。
  • 處理每個請求/查詢響應,在單獨的數據結構聚集並從等待行動者的列表中刪除發送者。
  • 一旦沒有演員等待 - 發送結果並停止當前演員(負責數據聚合的演員)。
  • 連接的情況下,ReceiveTimeout機制,當由於某種原因,不是所有的演員都能夠合理的時間內作出反應 - 當超時會打,你可能會返回故障或迄今收集的響應列表。

PS:不要使用TypedActor - 它對性能也不好,並且/將會過時。

+1

很感謝。問題讓我感到驚訝。所以你說的要求比一個告訴給發件人的響應要告訴更貴?是啊,WaitAll是讓我流眼淚的原因。偉大的聯繫,認爲這不是我想要的,然後成爲一塊真棒。 –

+3

Ask價格昂貴的原因是它既創建了一個任務,也是一個臨時演員,將會收到來自被問到的演員的迴應。臨時演員也註冊在'/ temp'下,註冊和取消註冊也有些貴。 –

+0

很好,非常感謝,非常有趣:D –