问题:
我很难理解为什么我的 Reporter actor 没有根据我的 Generator actor 中的以下语句接收消息:
reporter <! Message input
我的记者 Actor 如下:
let reporterActor (mailbox:Actor<_>) =
let rec loop() = actor { let! msg = mailbox.Receive()
match msg |> box :?> Command with
| Start -> ()
| Message v -> printf "%s" v
| Exit -> mailbox.Context.System.Terminate() |> ignore }
loop() |> ignore
基本上,启动一个控制台来接受用户的输入。我的 Generator actor 将该输入转发给我的 Reporter actor。但是,上面的代码永远不会被执行。
代码如下:
module Main
open System
open Akka.FSharp
open Akka.Actor
open Actors
type Command =
| Message of string
| Start | Exit
let reporterActor (mailbox:Actor<_>) =
let rec loop() = actor { let! msg = mailbox.Receive()
match msg |> box :?> Command with
| Start -> ()
| Message v -> printf "%s" v
| Exit -> mailbox.Context.System.Terminate() |> ignore }
loop() |> ignore
let generatorActor (reporter:IActorRef) (mailbox:Actor<_>) message =
let handle input = match input with
| "exit" -> mailbox.Context.System.Terminate |> ignore
| _ -> reporter <! Message input
handle (Console.ReadLine().ToLower())
[<EntryPoint>]
let main argv =
let system = System.create "system" (Configuration.load())
let reporterActor = spawn system "reporterActor" (actorOf(reporterActor))
let generatorActor = spawn system "generatorActor" (actorOf2(generatorActor reporterActor))
generatorActor <! Start
system.AwaitTermination ()
0
更新:
我了解到我可以通过用任意消息参数替换邮箱参数来触发我的 Reporter actor:
let reporterActor message =
match message |> box :?> Command with
| Start -> ()
| Message v -> printf "Reporting: %s" v
| Exit -> failwith "Kill this!"
我仍然不明白什么时候应该使用邮箱参数,什么时候应该依赖消息参数。
最佳答案
区别在于 actorOf 和 actorOf2 的工作方式。
actorOf 与spawn 结合创建一个actor 作为系统根的子级,它将使用函数'Message -> unit
处理消息。这是传递给它的。
actorOf2 与 spawn 结合创建一个 actor 作为您传入的 actor 的子级,并且该子级将使用函数 'Message -> unit
处理消息。那已经通过了。
您的记者 Actor 的原始函数签名是:
Actor<'Message> -> unit
你使用了spawn system "reporterActor" (actorOf(reporterActor))
在本例中,您所说的是创建的新参与者将收到的消息类型为 Actor<'Message>
类型。 。这个编译是因为 actorof 只是期望一个接受 'Message 的函数,而 'Message 是通用的,因此 Actor<'Message>
满足“消息参数”。
当您更新reporterActor的签名时,您将签名更改为'Message -> unit
这就是 actorOf 实际上想要接受的。
简而言之,泛型允许您的代码进行编译,因为“消息并未真正受到限制,也不应该真正受到限制。
来自:http://getakka.net/docs/FSharp%20API
actorOf
(fn : 'Message -> unit) (mailbox : Actor<'Message>) : Cont<'Message, 'Returned>
- uses a function, which takes a message as the only parameter. Mailbox parameter is injected by spawning functions.
actorOf2 (fn : Actor<'Message> -> 'Message -> unit) (mailbox : Actor<'Message>) : Cont<'Message, 'Returned>
- uses a function, which takes both the message and an Actor instance as the parameters. Mailbox parameter is injected by spawning functions. Example:> let handleMessage (mailbox: Actor<'a>) msg = > match msg with > | Some x -> printf "%A" x > | None -> () > > let aref = spawn system "my-actor" (actorOf2 handleMessage) let > blackHole = spawn system "black-hole" (actorOf (fun msg -> ()))
spawn (actorFactory : IActorRefFactory) (name : string) (f : Actor<'Message> -> Cont<'Message, 'Returned>) : IActorRef - spawns an actor using a specified actor computation expression. The actor can only be used locally.
All of these functions may be used with either the actor system or the actor itself. In the first case the spawned actor will be placed under /user root guardian of the current actor system hierarchy. In the second option the spawned actor will become a child of the actor used as the actorFactory parameter of the spawning function.
关于f# - 为什么我的 Actor 没有收到消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42142299/