2017-02-09 82 views
2

问题:为什么我的演员没有收到消息?

我努力理解为什么基于下面的语句是在我的发电机演员我的记者的演员是没有收到消息:

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 

基本上,一个控制台启动,接受来自用户的输入。我的生成器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 

更新:

我才知道,我可以用任意的消息参数更换邮箱参数触发我的记者的演员:

let reporterActor message = 
    match message |> box :?> Command with 
    | Start  ->() 
    | Message v -> printf "Reporting: %s" v 
    | Exit  -> failwith "Kill this!" 

我还是不明白我什么时候应该用邮箱吧rameter与何时我应该依赖消息参数。

回答

2

区别在于actorOf和actorOf2是如何工作的。

actorOf与spawn一起创建一个actor作为系统根目录的子节点,该子节点将处理传递给它的函数'Message -> unit的消息。

actorOf2与spawn一起创建一个actor,作为您传入的actor的子节点,子节点将使用传递的函数'Message -> unit处理消息。对于记者的演员

您的原始功能的签名是:

Actor<'Message> -> unit 

并且使用spawn system "reporterActor" (actorOf(reporterActor))

在这种情况下,你说该消息类型所创建的新的演员将获得将是键入Actor<'Message>。编译这个是因为actorof只需要一个接收'消息,并且'消息是通用的函数,因此Actor<'Message>满足'消息参数。

当您更新reporterActor的签名时,您将签名更改为'Message -> unit,这是actorOf实际上打算接受的内容。

简而言之,泛型允许您的代码进行编译,因为'消息不是真的受限制,也不应该是真的。

来自:http://getakka.net/docs/FSharp%20API

(fn : 'Message -> unit) (mailbox : Actor<'Message>) : Cont<'Message, 'Returned> actorOf - 使用一个函数,该函数的消息作为 的唯一参数。邮箱参数是通过产生 函数注入的。

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 ->())) 

产卵(actorFactory:IActorRefFactory)(名称:字符串)(F: 演员< '消息> - >续<' 消息,“返回>):IActorRef - 派生使用指定的 演员演员计算表达。演员只能在本地使用 。

所有这些功能都可以与演员系统或演员本身一起使用。在第一种情况下,衍生演员将被放置在当前演员系统层次结构的 /用户根监护人下。在 第二选项中,衍生演员将成为使用 作为演绎函数的actorFactory参数的演员的子代。

+0

谢谢Adam。你有测试演员的经验吗? –

+0

我没有,但是我发现这个链接https://petabridge.com/blog/how-to-unit-test-akkadotnet-actors-akka-testkit/它可能对测试有帮助。我不确定是否有F#化的库,但我相信你可以使用F#来处理它。 – awright18

相关问题