F#Akka-等待一组演员完成后再开始下一组

F#Akka-等待一组演员完成后再开始下一组,f#,akka,actor,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 {

这里有一个玩具示例,我创建了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"
    ()
)
开放系统
打开阿克卡,演员
打开Akka.Configuration
打开Akka.FSharp
让system=system.create“test”(Configuration.defaultConfig())
让我的演员(邮箱:演员)=
演员{
设rand=System.Random()
let!message=mailbox.Receive()
将消息与匹配
|“第一”->printfn“第一组”
|->printfn“第二组”
Thread.SpinWait(rand.Next(1001000))
}
让actorArray=Array.create 200(生成系统“myActor”myActor)
{0..199}
actorArray.[a]序列iter(乐趣a->
actorArray.[a]序列iter(乐趣a->
阿克特拉雷
我希望前100名演员在向第二组发送消息之前完成(即打印和终止),但这不会发生


我已经开始研究这个模块,但我不确定如何实现它。

所以我创建了一个解决方案,不确定它是否是最惯用的,但它确实起到了作用

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
开放系统
打开阿克卡,演员
打开Akka.Configuration
打开Akka.FSharp
让system=system.create“MySystem”(Configuration.defaultConfig())
让我的演员(邮箱:演员)=
演员{
设rand=System.Random()
let!message=mailbox.Receive()
让发件人=邮箱。发件人()
将消息与匹配
|“第一”->printfn“第一组”
|->printfn“第二组”
Thread.SpinWait(rand.Next(1001000))
发送者)=
设可变i=99
让actorArray=Array.create 200(生成系统“myActor”myActor)
{0..199}
actorArray.[a]序列iter(乐趣a->
阿克特拉雷
一、国际热核实验堆(乐趣a->
阿克特拉雷
本质上,所发生的事情是一个外部参与者设置环境,并在其递归循环外部开始第一组任务。任务参与者现在在完成时发送
“Done”
,这在
myMonitor
递归循环内处理


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

首先,我认为您调用了错误的Akka方法来创建您的系统。如果要从F#使用
Akka.FSharp.system.create
函数,您调用的是
Akka.Actor.ActorSystem.createe
相反。我不了解Akka,所以我可能无法帮助您解决其余的问题,但我至少可以帮助您修复一个错误。感谢您的建议,这两行代码的行为似乎相同,但我对其进行了编辑以使其符合规范!我从文档中得到的印象是,差异很微妙,您还看不到它们——但F#v例如,Version将允许您使用F#引号(
符号)稍后。看看Akka的,看起来你想创建一个actor,在第一组的所有100个上调用该方法,当所有100个都终止时,然后并且只有那时你才会向第二组的100个actor发送消息。我还没有找到在F#中调用该方法的正确语法,这就是为什么我在这里留下评论的原因我不想写一个完整的答案,因为我不能确切地告诉你怎么做。但也许这就足够让你开始了。所以这就是我在问题中提到的
monitor
功能。我遇到的问题是,我无法在
F#
语法中理解
self
,因此无法在内部创建监视器监控参与者。另一种选择是在外部创建它们,并将监控组发送给监控参与者。我发布了一个更简单的系统,但我也可以尝试这种可能性并发布结果。