f# 异步取消或继续

问题描述 投票:0回答:1

如何实现一个异步函数,该函数将检查多个并行异步函数的每个结果,并在找到某个结果时取消所有结果(比如 bool 返回 false)。否则,它将让所有异步函数完成,然后返回最终结果(例如 bool true)。我已经尝试过 F# snippets 站点中的 Async.Choice,但它使用 Async.FromContinuations 只允许您调用延续一次。

asynchronous f#
1个回答
0
投票

假设您有一个

async
可以完成一些工作:

let computeSomething (x : int) =
  async {
    do! Async.Sleep (x * 1000)

    return x * 2 + x
  }

让我们添加一些额外的代码,以便我们可以查看是否发生取消:

let computeSomething (x : int) =
  async {
    // To prove that cancellation is happening
    use! watcher =
      Async.OnCancel
        (fun () -> printfn $"Computation for %i{x} was cancelled")

    do! Async.Sleep (x * 1000)

    return x * 2 + x
  }

现在,我们可以使用

Async.Parallel
并行运行其中许多:

async {
  let! results =
    [
      for x in [ 1; 7; 2; 3; 4; 5 ] do
        computeSomething x
    ]
    |> Async.Parallel

  printfn "%A" results
}

Async.Parallel
有一个有用的属性,如果一个任务失败,其余任务将被取消。

因此,我们可以将

computeSomething
包装成
async
来检查结果:

let computeSomethingAndFailIfWrong (x : int) =
  async {
    let! result = computeSomething x

    if result > 10 then
      failwith $"Something went wrong for input %i{x}"

    return result
  }

并将其交给

Async.Parallel

async {
  let! results =
    [
      for x in [ 1; 7; 2; 3; 4; 5 ] do
        computeSomethingAndFailIfWrong x
    ]
    |> Async.Parallel

  printfn "%A" results
}
|> Async.RunSynchronously

运行此程序,我们观察到正在进行的任务被取消:

Computation for 5 was cancelled
Computation for 7 was cancelled
System.Exception: Something went wrong for input 4
© www.soinside.com 2019 - 2024. All rights reserved.