F#中异步操作的顺序执行链接

时间:2012-03-08 16:19:08

标签: asynchronous f# sequential-workflow

是否有任何原语构成async1 然后 async2,类似于并行执行规划的并行功能?

进一步澄清,我有2个异步计算

  let toto1 = Async.Sleep(1000)
  let toto2 = Async.Sleep(1000)

我想创建一个由toto1和toto2的顺序组合构成的新异步计算

  let toto = Async.Sequential [|toto1; toto2|]

一旦开始,toto将运行toto1然后toto2,并将在2000个时间单位后结束

2 个答案:

答案 0 :(得分:4)

async.Bind操作是异步工作流为顺序组合提供的基本原语 - 在async块语法中,与let!对应。您可以使用它来表示两个计算的顺序组合(如Daniel所示)。

但是,如果你有一个丹尼尔定义的操作<|>,那么它的表达力不足以实现async.Bind,因为当你使用async.Bind顺序编写事物时,第二个计算可能取决于关于第一个的结果。 <e2>可能会使用v1

async.Bind(<e1>, fun v1 -> <e2>)

如果您正在撰写<e1> <|> <e2>,那么这两项操作必须是独立的。这就是为什么这些库基于Bind的原因 - 因为它是顺序组合的表现形式,而不是你遵循Async.Parallel结构时所获得的那种。

如果你想要一些行为类似于Async.Parallel并采用数组的东西,那么最简单的选择是在循环中使用let!强制实现(但你也可以使用递归和列表):< / p>

let Sequential (ops:Async<'T>[]) = async {
  let res = Array.zeroCreate ops.Length
  for i in 0 .. ops.Length - 1 do
    let! value = ops.[i]
    res.[i] <- value 
  return res }

答案 1 :(得分:2)

我不确定“原始”是什么意思。 Async.Parallel是一个功能。以下是运行两个异步的几种方法:

同时:

Async.Parallel([|async1; async2|])

async {
  let! child = Async.StartChild async2
  let! result1 = child
  let! result2 = async1
  return [|result1; result2|]
}

顺序地:

async {
  let! result1 = async1
  let! result2 = async2
  return [|result1; result2|]
}

你可以在最后两个中返回元组。我保持返回类型与第一个相同。

我会说let! do!async { }块中的let (<|>) async1 async2 = async { let! r1 = async1 let! r2 = async2 return r1, r2 } 尽可能接近使用原语。

修改

如果有这些讨厌的语法,你可以定义一个组合器:

async1 <|> async2 |> Async.RunSynchronously

然后执行:

{{1}}