问题:
我很难理解为什么我的Reporter actor没有根据我的Generator actor中的以下语句接收消息:
reporter <! Message input
我的记者演员如下:
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演员将该输入转发给我的Reporter演员。但是,上面的代码永远不会被执行。
代码如下:
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
更新
我了解到我可以通过用任意消息参数替换mailbox参数来触发我的Reporter:
let reporterActor message =
match message |> box :?> Command with
| Start -> ()
| Message v -> printf "Reporting: %s" v
| Exit -> failwith "Kill this!"
我仍然不明白何时应该使用邮箱参数而不是我应该依赖邮件参数。
答案 0 :(得分:2)
区别在于actorOf和actorOf2的工作方式。
actorOf与spawn一起创建一个actor作为系统根的子节点,它将处理传递给它的函数'Message -> unit
的消息。
actorOf2与spawn一起创建一个actor作为你传入的actor的子节点,子节点将处理传递的函数'Message -> unit
的消息。
您对记者演员的原始功能签名是:
Actor<'Message> -> unit
您使用了spawn system "reporterActor" (actorOf(reporterActor))
在这种情况下,您说的是创建的新actor将接收的消息类型将是Actor<'Message>
类型。这是因为actor只需要一个带有&#39;消息的函数,而且消息是通用的,因此Actor<'Message>
满足了&#39; Message参数。
当您更新了reporterActor的签名时,您将签名更改为'Message -> unit
,这是actorOf实际上要接受的内容。
简而言之,泛型允许您的代码编译,因为“消息”并非真正受到限制,也不应该真的受到限制。
来自:http://getakka.net/docs/FSharp%20API
actorOf
(fn : 'Message -> unit) (mailbox : Actor<'Message>) : Cont<'Message, 'Returned>
- 使用一个函数,它接收一条消息 唯一的参数。邮箱参数由产卵注入 功能
actorOf2 (fn : Actor<'Message> -> 'Message -> unit) (mailbox : Actor<'Message>) : Cont<'Message, 'Returned>
- 使用一个函数 将消息和Actor实例作为参数。 邮箱参数由产生函数注入。例如:> 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: 演员&LT;&#39;消息&GT; - &GT; Cont&lt;&#39;消息,&#39;返回&gt;):IActorRef - 生成一个 使用指定的actor计算表达式的actor。演员可以 只能在本地使用。
所有这些功能都可以与演员系统或演员系统一起使用 演员本身。在第一种情况下,产生的演员将被放置在 /当前actor系统层次结构的用户root监护人。在里面 第二个选项,衍生的演员将成为演员使用的孩子 作为产卵函数的actorFactory参数。