Question

I've been trying to learn how to use asynchronous message based methods. Below is a simplified version of what I was trying to do. I'm trying to use a finite state machine within a MailboxProcessor within an object. Overall it appears that the logic can be much more straightforward compared to using event based methods. I have an issue though when I try to use Async.Parallel. In the code following the printfn "Eval %i" v statement is getting evaluated twice for i1 & i2 instead of just one time for each. Which leads me to believe that I am not properly using Async.Parallel. Is there an alternative method that should be used within an asynchronous workflow?

type Input(v) = 

    let agent = 
        MailboxProcessor.Start(fun inbox -> 
            let rec loop() = 
                async { 
                    let! (msg : AsyncReplyChannel<int>) = inbox.Receive()
                    printfn "Eval %i" v
                    msg.Reply(v)
                    return! loop()
                }
            loop())

    member this.Eval = agent.PostAndAsyncReply(fun r -> r)

let i1 = Input(1)
let i2 = Input(2)

async { 
    let! nodeValues = [ i1; i2 ]
                      |> Seq.map(fun n -> n.Eval)
                      |> Async.Parallel
    return nodeValues
}
|> Async.RunSynchronously
Was it helpful?

Solution

This is a bug in F# 3.0. Async.Parallel calls Seq.toArray twice. Run your code under F# 3.1 and it will only print once. Here's the fix in the F# source repository.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top