F#Akka - 在开始下一组之前等待一组演员完成

时间:2016-04-20 08:17:46

标签: f# akka actor

所以我在这里有一个玩具示例,我在那里创建200个演员然后发送前100个"first"消息,然后发送最后100个"second"消息。

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模块,但我并不确定如何实施它。

1 个答案:

答案 0 :(得分: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设置环境并开始第一组任务之外的递归循环。任务中的actor现在在完成时发送"Done",并在myMonitor递归循环内处理。

一旦myMonitor收到第一个块的所有消息,它就会启动第二个消息。