我从Don Syme的第13章
获得了专家F#的代码示例open System.ComponentModel
open System.Windows.Forms
let worker = new BackgroundWorker()
let numIterations = 1000
worker.DoWork.Add(fun args ->
let rec computeFibonacci resPrevPrev resPrev i =
//compute next result
let res = resPrevPrev + resPrev
//at the end of the computation and write the result into the mutable state
if i = numIterations then
args.Result <- box res
else
//compute the next result
computeFibonacci resPrev res (i+1)
computeFibonacci 1 1 2)
worker.RunWorkerCompleted.Add(fun args ->
MessageBox.Show(sprintf "result = %A" args.Result) |> ignore)
//execute the worker
worker.RunWorkerAsync()
我知道这段代码可以计算斐波纳契数,但我的问题是,有没有办法让我为计算斐波那契做函数然后将它包装在后台工作程序代码中?用例子会更好:)谢谢
答案 0 :(得分:3)
只是为了稍微简化Ankur的解决方案 - 在这种情况下您不需要使用lazy
值。最简单的方法是先声明computeFibonacci
函数,然后从DoWork
事件中调用它。
重要的一点是,您需要更改computeFibonacci
以返回结果,而不是将其存储到args
,因为args
仅在从DoWork
调用时才可用:
let numIterations = 1000
let rec computeFibonacci resPrevPrev resPrev i =
//compute next result
let res = resPrevPrev + resPrev
//at the end of the computation and write the result into the mutable state
if i = numIterations then
// Return result from the function
res
else
//compute the next result
computeFibonacci resPrev res (i+1)
然后,您可以创建调用compueFibonacci
的后台工作程序,并将结果存储在args
中:
let worker = new BackgroundWorker()
worker.DoWork.Add(fun args ->
// Call fibonacci and store the result in `Result`
// (the F# compiler converts number to `obj` automatically)
args.Result <- computeFibonacci 1 1 2)
worker.RunWorkerCompleted.Add(fun args ->
MessageBox.Show(sprintf "result = %A" args.Result) |> ignore)
worker.RunWorkerAsync()
答案 1 :(得分:1)
是的,你可以这样做。使用一些“懒惰”以及使用currying的更高阶函数,也可能有其他技术。事实上,使用它可以包装产生结果的任何函数。
let worker = new BackgroundWorker()
let numIterations = 1000
let rec computeFibonacci resPrevPrev resPrev i =
let res = resPrevPrev + resPrev
if i = numIterations then
box res
else
computeFibonacci resPrev res (i+1)
let wrapper (result:obj Lazy) (args:DoWorkEventArgs) = args.Result <- result.Force()
worker.DoWork.Add( lazy (computeFibonacci 1 1 2) |> wrapper)
worker.RunWorkerCompleted.Add(fun args ->
MessageBox.Show(sprintf "result = %A" args.Result) |> ignore)
//execute the worker
worker.RunWorkerAsync()