нужна помощь для этого фонового рабочего кода - PullRequest
0 голосов
/ 19 июня 2011

Я получил этот пример кода от Эксперта F # Дона Сайма из главы 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()

Я знал, что этот код вычисляет число Фибоначчи, но мой вопрос, есть ли способ сделать функцию длявычислить Фибоначчи, а затем обернуть его в фоновом рабочем коде?с примером было бы лучше :) спасибо

Ответы [ 2 ]

3 голосов
/ 19 июня 2011

Просто чтобы немного упростить решение от 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 голос
/ 19 июня 2011

Да, вы можете сделать это. Используя немного «лени», а также функцию более высокого порядка, используя карри, может быть и другая техника. С его помощью вы можете обернуть любую функцию, которая дает результат.

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