f# - 为什么我的 Actor 没有收到消息?

标签 f# akka.net

问题:

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

相关文章:

f# - 有没有更惯用的方法来生成无限的 uint64 序列?

powershell - 在 Powershell 中加载 F# 程序集并创建记录表达式

c# - Akka.net DI - 如何通过 DI 注入(inject)两个 Actor ?

c# - AKKA.NET 问题 : Is it a good idea to have more than one ActorSystem in an application?

unit-testing - 如何在F#中保持方法返回类型 'void'?

unit-testing - 让 Visual Studio 2013 Express for Desktop 检测到 F# 测试

inheritance - F# 静态覆盖

c# - 我如何调整生产者 Actor 的速度,以便它不会向消费者 Actor 传达太多消息

c# - Akka.Net 中 UntypedActor 和 ReceiveActor 有什么区别?

c# - .Net Standard 4.7.1 在序列化期间无法加载 System.Private.CoreLib