简体   繁体   中英

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM