2

语言中是否有任何原语来组合 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 个时间单位后结束

4

2 回答 2

4

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

但是,如果您有<|>Daniel 定义的操作,那么它的表达能力不足以实现async.Bind,因为当您使用 顺序组合事物时async.Bind,第二次计算可能取决于第一次计算的结果。<e2>可以使用v1

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

如果您正在编写<e1> <|> <e2>,那么这两个操作必须是独立的。这就是库基于的原因Bind- 因为它比您遵循Async.Parallel.

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

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 }
于 2012-03-08T21:17:10.637 回答
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
于 2012-03-08T16:36:09.897 回答