【问题标题】:need help for this background worker code需要此后台工作人员代码的帮助
【发布时间】:2011-06-19 05:49:06
【问题描述】:

我从第 13 章的 Don Syme 的 Expert 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()

我知道这段代码计算斐波那契数,但我的问题是,有什么方法可以让我创建计算斐波那契的函数,然后将其包装在后台工作代码中?有例子会更好:)谢谢

【问题讨论】:

    标签: .net multithreading f# backgroundworker


    【解决方案1】:

    只是为了稍微简化 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()
    

    【讨论】:

    • 感谢托马斯先生的回答。但是,F# 编译器自动将数字转换为“obj”是什么意思? BackgroundWorker 类是否这样做?
    • @Yabert - 我的意思是你不必显式调用 box 函数(因为它是 Ankur 的解决方案)。
    【解决方案2】:

    是的,你可以这样做.. 使用一点“懒惰”以及使用 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()
    

    【讨论】:

    • 感谢安库尔。你的代码也有效。但我更喜欢 Thomas 先生的代码,因为它更简单。但是非常感谢你:)
    猜你喜欢
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 2010-11-04
    • 2021-02-06
    • 2013-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多