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