来自F#的Async.Parallel操作的结果是否保证在提交的作业中到达?我的示例代码按顺序返回结果,但我在MSDN文档或F#规范中找不到任何提及,确保必须成为案例 - 这不是巧合。
以下是我的示例代码:
let r = System.Random()
Async.Parallel [
for i in 0..10 ->
async {
let rand_num = r.Next(10)
do! Async.Sleep(rand_num) (* Simulate jobs taking a variable amount of time *)
printfn "%i %i" i rand_num
return i
}
]
|> Async.RunSynchronously
|> printfn "%A"
这是输出。
0 0
5 1
4 1
3 3
10 6
9 4
7 5
2 5
1 5
8 7
6 9
[|0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]
您可以看到,在此运行中,异步函数以不确定的顺序完成,但生成的数组已排序。这种行为有保障吗?
答案 0 :(得分:11)
目前,编写函数的源代码以强制执行此保证。查看control.fs around line #1300的定义,我们可以看到将结果放入输出数组的函数是
let recordSuccess i res =
results.[i] <- res;
finishTask(Interlocked.Decrement count)
在此段中调用此函数
tasks |> Array.iteri (fun i p ->
queueAsync
innerCTS.Token
// on success, record the result
(fun res -> recordSuccess i res)
其中tasks
按排序顺序包含原始任务。这可以保证输出列表与输入的顺序相同。
<强>更新强>
规范至少似乎意味着订单是固定的 - 它包含以下代码:
let rec fib x = if x < 2 then 1 else fib(x-1) + fib(x-2)
let fibs =
Async.Parallel [ for i in 0..40 -> async { return fib(i) } ]
|> Async.RunSynchronously
printfn "The Fibonacci numbers are %A" fibs //I changed this line to be accurate
System.Console.ReadKey(true)
如果规范不保证输出顺序,则此代码不正确。