When running the following code
open System
open Microsoft.FSharp.Control
type Message(id, contents) =
static let mutable count = 0
member this.ID = id
member this.Contents = contents
static member CreateMessage(contents) =
count <- count + 1
Message(count, contents)
let mailbox = new MailboxProcessor<Message>(fun inbox ->
let rec loop count =
async { printfn "Message count = %d. Waiting for next message." count
let! msg = inbox.Receive()
printfn "Message received. ID: %d Contents: %s" msg.ID msg.Contents
return! loop( count + 1) }
loop 0)
mailbox.Start()
mailbox.Post(Message.CreateMessage("ABC"))
mailbox.Post(Message.CreateMessage("XYZ"))
//System.Threading.Thread.Sleep(500)
Console.WriteLine("Press any key...")
Console.ReadLine() |> ignore
I get the following result
> Press any key...
Message count = 0. Waiting for next message.
Message received. ID: 1 Contents: ABC
Message count = 1. Waiting for next message.
Message received. ID: 2 Contents: XYZ
Message count = 2. Waiting for next message.
I would expect the msg press anykey to come somewhat after the first message…
And if I include the sleep, it indeed comes after.
So my question is :
Is the take away lesson of this that you can not expect any particular ordering when using async methods. aka, the code inside async can start with no specific precedence ?
From the docs for
mailboxProcessor(where this code sample is from)Note –
Postmakes no gurantees about processing – that is the whole idea behind async. If you need to wait for the computation to finish you need to usePostAndReply– although at this point you lose some of the benefit of multithreading.The
MailboxProcessorwill always process the messages in order, but unless you wait for it, the messages won’t have finished processing