需要帮助这个后台工作者代码

时间:2011-06-19 05:49:06

标签: .net multithreading f# backgroundworker

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

我知道这段代码可以计算斐波纳契数,但我的问题是,有没有办法让我为计算斐波那契做函数然后将它包装在后台工作程序代码中?用例子会更好:)谢谢

2 个答案:

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