Asynchronous 如何在异步工作流中使用Async.Parallel?

Asynchronous 如何在异步工作流中使用Async.Parallel?,asynchronous,f#,mailboxprocessor,Asynchronous,F#,Mailboxprocessor,我一直在尝试学习如何使用基于消息的异步方法。下面是我试图做的一个简化版本。我试图在对象中的MailboxProcessor中使用有限状态机。总的来说,与使用基于事件的方法相比,逻辑似乎更加简单。但是,当我尝试使用Async.Parallel时,我遇到了一个问题。在printfn“Eval%i”后面的代码中,v语句对i1和i2进行了两次评估,而不是一次评估一次。这让我相信我没有正确地使用Async.Parallel。异步工作流中是否应该使用其他方法 type Input(v) = le

我一直在尝试学习如何使用基于消息的异步方法。下面是我试图做的一个简化版本。我试图在对象中的
MailboxProcessor
中使用有限状态机。总的来说,与使用基于事件的方法相比,逻辑似乎更加简单。但是,当我尝试使用
Async.Parallel
时,我遇到了一个问题。在
printfn“Eval%i”后面的代码中,v
语句对
i1
i2
进行了两次评估,而不是一次评估一次。这让我相信我没有正确地使用
Async.Parallel
。异步工作流中是否应该使用其他方法

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
类型输入(v)=
让代理=
MailboxProcessor.Start(有趣的收件箱->
让rec循环()
异步{
let!(msg:AsyncReplyChannel)=收件箱。接收()
打印fn“评估%i”v
答复(五)
return!loop()
}
循环())
member this.Eval=agent.PostAndAsyncReply(fun r->r)
设i1=输入(1)
设i2=输入(2)
异步{
让!nodeValues=[i1;i2]
|>序列图(乐趣n->n.Eval)
|>异步并行
返回节点值
}
|>异步运行

这是F#3.0中的一个bug
Async.Parallel
调用
Seq.toArray
两次。在F#3.1下运行代码,它将只打印一次

您不需要
async{}
块<代码>[i1;i2]|>Seq.map(fun n->n.Eval)|>Async.Parallel |>Async.RunSynchronously将起作用。感谢您的评论,但实际实现不会同步运行。我的问题是如何在异步工作流中并行计算异步返回数组(本例中为
Eval
方法)。有关更大的示例,请参阅。可能只需将
Async.Parallel
的结果传递到
Async.Ignore |>Async.Start
?一旦
Eval
的结果完成后,您希望如何处理它们?在VS2010下的fsi中,我只看到
Eval 1
Eval 2
与上述代码一起打印一次,这是意料之中的。你的环境是什么?我开始怀疑我是否偶然发现了一个bug。如果我将
nodeValues
定义更改为
let,它将按预期运行!nodeValues=[|i1;i2 |]|>Array.map(fun->n.Eval)|>Async.Parallel
。以前有人在异步工作流中遇到过
Seq.map
Array.map
之间的不同行为吗?感谢您的帮助。我没想到要检查github的源代码。看起来
Async.Parallel
方法有足够的依赖性,如果我想在VS2012中使用3.1方法,它不仅仅是一个小片段。当我使用
Array.map
并从一个数组开始进入
Async.Parallel
方法时,
Seq.toArray
调用是否有效地被忽略了?我想我要问的是,在F#3.0中使用
Array.map
解决了这个问题,还是需要在3.0中完全避免异步.Parallel?谢谢当然可以,如果使用Array.map,它将正常工作。错误仍然会发生在F#源中,但它只是将数组转换为序列,然后再返回数组两次。我认为这是一个设计缺陷
Async.parallel
应该以数组开始,而不是序列。它实际上不支持延迟评估,这可能会导致一些用户误入歧途。