为什么我的演员不接收消息?

时间:2017-02-09 16:45:44

标签: f# akka.net

问题:

我很难理解为什么我的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!"

我仍然不明白何时应该使用邮箱参数而不是我应该依赖邮件参数。

1 个答案:

答案 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参数。