2012-06-15 14 views
0

我有点新手与异步工作流程,我认为它有些东西我不太了解...我正在关注这本书真实世界的函数式编程和它写入异步原始这样在f#中使用Async.FromContinuations自定义异步原语功能

let Sleep(time) = 
    Async.FromContinuations(fun (cont, econt, ccont) -> 
    let tmr = new System.Timers.Timer(time, AutoReset = false) 
    tmr.Elapsed.Add(fun _ -> cont()) 
    tmr.Start() 
);; 

我试着写我自己的异步原始使用一个非常缓慢的阶乘的实现,代码是:

let rec factorial(n : int) (mem : bigint) = 
    match n with 
    | 0 | 1 -> printfn "%A" mem 
    | _ -> factorial (n - 1) (mem * bigint(n)) 


let BigFactorial(numero,mesaje)= 
    Async.FromContinuations(fun (cont,error,cancelation) -> 
           printfn "begin number: %s" mesaje 
           factorial numero 1I |>ignore 
           printfn "End number: %s ." mesaje 
           cont()) 

现在我写这

Async.RunSynchronously(async{ 
    printfn "Start!!..." 
    do! BigFactorial(30000,"30M") 
    do! BigFactorial(10000, "10M") 
    printfn "End!!..." 
}) 

,但它不是在精确的异步方式运行....

Start!!... 
begin number: 30M 
2759537246219...(A nice long number!) 
end number: 30M . 
begin number: 10M . 
2846259680917054518906...(other nice number) 
End!!... 

如果我并行执行它,然后做工不错...

let task1 = async{ 
    printfn "begin" 
    do! BigFactorial(30000,"30") 
    printfn "end..." 
} 

let task2 = async{ 
    printfn "begin" 
    do! BigFactorial(10000,"10") 
    printfn "end!!..." 
} 


Async.RunSynchronously(Async.Parallel[task1;task2]) 

begin 
begin: 30 
begin 
begin: 10M 

//long numbers here 

end.... 
end..... 

,但我希望知道原因(或几个原因!)为什么第一个代码不起作用... 非常感谢我感谢任何帮助...

回答

2

一样async绑定,do!在当前线程上运行,因此您的两个连续的do!按顺序运行。

如果你希望它们并行运行,你一定要说这么明确:

async { 
    printfn "Start!!..." 
    let! tokenA = BigFactorial (30000, "30M") |> Async.StartChild // on new thread 
    let! tokenB = BigFactorial (10000, "10M") |> Async.StartChild // on new thread 
    do! tokenA // block until `BigFactorial (30000, "30M")` finishes 
    do! tokenB // block until `BigFactorial (10000, "10M")` finishes 
    printfn "End!!..." } 
|> Async.RunSynchronously