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中的一个bugAsync.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
应该以数组开始,而不是序列。它实际上不支持延迟评估,这可能会导致一些用户误入歧途。