Search code examples
.netmultithreadingf#backgroundworker

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


Solution

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