2016-04-20 3 views
1

Итак, у меня есть пример с игрушкой, где я создаю 200 актеров, а затем отправляю первые 100 сообщений "first", прежде чем отправлять последние 100 сообщений "second".F # Akka - Дождитесь окончания одной группы актеров до начала следующей группы

open System 
open Akka.Actor 
open Akka.Configuration 
open Akka.FSharp 

let system = System.create "test" (Configuration.defaultConfig()) 

let myActor (mailbox: Actor<_>) = 
    actor { 
     let rand = System.Random() 
     let! message = mailbox.Receive() 
     match message with 
     | "first" -> printfn "first group" 
     | _ -> printfn "second group" 
     Thread.SpinWait (rand.Next(100,1000)) 
    } 
let actorArray = Array.create 200 (spawn system "myActor" myActor) 

{0..199} |> Seq.iter (fun a -> 
    actorArray.[a] <- spawn system (string a) myActor 
) 

// First group 
{0..100} |> Seq.iter(fun a -> 
    actorArray.[a] <! "first" 
    () 
) 
// Second group 
{101..199} |> Seq.iter(fun a -> 
    actorArray.[a] <! "second" 
    () 
) 

То, что я хотел бы для первых 100 сто актеров для завершения (то есть печатать и прекратить) перед отправкой сообщения ко второй группе, которая не бывает.

Я начал искать модуль Akka's F# monitoring, но я не совсем уверен, как его реализовать.

+3

Для начала, я думаю, вы вызываете неправильный метод Akka для создания вашей системы. [Документы API Akka F #] (http://getakka.net/docs/FSharp%20API#monitoring) говорят, чтобы вызвать функцию «Akka.FSharp.System.create», если вы собираетесь использовать ее из F #, и вместо этого вы вызываете «Akka.Actor.ActorSystem.Create». Я не знаю Акку, поэтому я не могу помочь вам с остальными, но я могу хотя бы помочь вам исправить эту ошибку. – rmunn

+0

Спасибо за совет, обе линии, похоже, имеют такое же поведение, но я отредактировал его, чтобы сохранить его в спецификации! – Darkstarone

+1

Я получаю впечатление от документов, что различия тонкие, и вы их еще не увидите - но версия F # позволит вам, скажем, использовать котировки F # («<@ @>» в дальнейшем). – rmunn

ответ

1

Итак, я создал решение, не уверен, что он самый идиоматический, но он выполняет эту работу!

open System 
open Akka.Actor 
open Akka.Configuration 
open Akka.FSharp 

let system = System.create "MySystem" (Configuration.defaultConfig()) 

let myActor (mailbox: Actor<_>) = 
    actor { 
     let rand = System.Random() 
     let! message = mailbox.Receive() 
     let sender = mailbox.Sender() 
     match message with 
     | "first" -> printfn "first group"  
     | _ -> printfn "second group" 
     Thread.SpinWait (rand.Next(100,1000)) 
     sender <! "Done" 
    } 

let myMonitor (mailbox: Actor<_>) = 
    let mutable i = 99 
    let actorArray = Array.create 200 (spawn system "myActor" myActor) 
    {0..199} |> Seq.iter (fun a -> 
     actorArray.[a] <- spawn system (string a) myActor 
     () 
    ) 
    // First group 
    {0..100} |> Seq.iter(fun a -> 
     actorArray.[a] <! "first" 
     () 
    ) 
    let rec loop() = 
     actor { 
      let! message = mailbox.Receive() 
      match message with 
      | _ -> 
       i <- (i - 1) 
       if (i = 0) then 
        // Second group 
        {101..199} |> Seq.iter(fun a -> 
         actorArray.[a] <! "second" 
         () 
        ) 
      return! loop() 
     } 
    loop() 

let mon = spawn system "myMon" myMonitor 

В сущности, что происходит внешний актер myMonitor настраивает среду и начинает первый набор задач вне его рекурсивного цикла. Актеры на задаче теперь отправляют "Done", когда они завершатся, и это обрабатывается в рекурсивном цикле myMonitor.

После того, как myMonitor получил все сообщения от первого блока, он начинает второй.

Смежные вопросы