need help for this background worker code
I get this code example from Expert F# by Don Syme from chapter 13
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()
i knew that this code compute fibonacci number, but my question is, is there any way that i make the function for compute fibonacci and then wrap it in the background worker code? with开发者_如何学运维 example would be better :) thanks
Just to slightly simplify the solution by Ankur - you don't need to use lazy
values in this case. The simplest way is to declare the computeFibonacci
function first and then call it from the DoWork
event.
The important point that you need to change computeFibonacci
to return the result instead of storing it to args
because args
are only available when called from 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)
Then you can create background worker that calls compueFibonacci
and storest the result in 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()
Yes, you can do that.. Using a bit of "laziness" as well as higher order function using currying , there may be other technique as well. Infact using this you can wrap any function which produce a result.
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()
精彩评论