基本的 Hello World

让我们首先创建一个简单的 Hello World! MailboxProcessor 处理一种类型的消息并打印问候语。

你需要消息类型。它可以是任何东西,但 Discriminated Unions 在这里是一个自然的选择,因为它们列出了一个地方的所有可能的情况,你可以在处理时轻松使用模式匹配。

// In this example there is only a single case, it could technically be just a string
type GreeterMessage = SayHelloTo of string

现在定义处理器本身。这可以通过 MailboxProcessor<'message>.Start 静态方法完成,该方法返回一个已准备就绪的已启动处理器。你也可以使用构造函数,但是你需要确保稍后启动处理器。

let processor = MailboxProcessor<GreeterMessage>.Start(fun inbox ->
    let rec innerLoop () = async {
        // This way you retrieve message from the mailbox queue
        // or await them in case the queue empty.
        // You can think of the `inbox` parameter as a reference to self.
        let! message = inbox.Receive()
        // Now you can process the retrieved message.
        match message with
        | SayHelloTo name ->
            printfn "Hi, %s! This is mailbox processor's inner loop!" name
        // After that's done, don't forget to recurse so you can process the next messages!
        innerLoop()
    }
    innerLoop ())

Start 的参数是一个引用 MailboxProcessor 本身的函数(当你刚创建它时它还不存在,但是一旦函数执行就可以使用)。这使你可以访问其各种 ReceiveScan 方法来访问邮箱中的邮件。在这个函数中,你可以做任何你需要的处理,但通常的方法是一个无限循环,它逐个读取消息并在每个消息之后调用它们。

现在处理器已准备好,但它没有任何意义! 为什么?你需要向其发送消息以进行处理。这是通过 Post 方法变体完成的 - 让我们使用最基本的,即发生的方法。

processor.Post(SayHelloTo "Alice")

这会向 processor 的内部队列(邮箱)发送一条消息,并立即返回,以便调用代码可以继续。一旦处理器检索到消息,它就会处理它,但是这将以异步方式发布它,并且它很可能在一个单独的线程上完成。

很快你就会看到信息 Hi, Alice! This is mailbox processor's inner loop! 打印到输出中,你准备好了更复杂的样本。