2014-06-16 102 views
6

F#的Async.Parallel操作的结果是否保证在订单作业中提交?我的示例代码按顺序返回结果,但我无法在MSDN文档或F#规范中找到任何提及,请确保此必须是就是这种情况 - 这并非巧合。F#Async.Parallel结果保证按顺序吗?

这里是我的示例代码:

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

您可以看到,在此次运行中,异步函数以不确定的顺序完成,但结果数组已排序。这种行为是否有保证?

回答

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具有原始任务排序订购。这保证了输出列表与输入顺序相同。

UPDATE

该规范至少似乎暗示顺序是固定的 - 它包含以下代码:

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) 

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

+1

这让我想起整数的'GetHashCode'方法只返回整数的事实。这是一个实现细节,而不是规范要求。我会建议不要依赖于这种行为。 –

+3

@ChristopherStevenson - 我做了一些挖掘,规范似乎至少暗示输出顺序是有保证的 –