F#Async.Parallel结果是否保证有序?

时间:2014-06-16 01:20:08

标签: f# f#-async

来自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|]

您可以看到,在此运行中,异步函数以不确定的顺序完成,但生成的数组已排序。这种行为有保障吗?

1 个答案:

答案 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)

如果规范不保证输出顺序,则此代码不正确。