进度条异步在FsXaml应用程序

0

的问题

在我 F# (FsXaml/代码) 应用程序,我想用一个进度条没有使用的背景工作人员为我做的。 基于上文在互联网上(链接是 在这里)时,我试图使用异步的工作流程。

我创建了基于代码(到一些延伸),在该例子在本文前述的,但它没有工作,因为我曾预期的。 目前的螺纹(UI线)仍然受阻,如果没有异步的码在那里。 没有开关的背景线发生。 进度条会被激活唯一后的长期运行的操作已经完成。 除 onThreadPool 功能没有效果。

我的问题是:什么是错误的,在我的代码和如何使它的权利?

type MainWindowXaml = FsXaml.XAML<"XAMLAndCodeBehind/MainWindow.xaml">

type MainWindow() as this =

    inherit MainWindowXaml()

    //....some code....

    let ButtonClick _ = 
   
        //....some code....
       
        let longRunningOperation() = //....some long running operation (reading from Google Sheets)....            
             
        let progressBar() = this.ProgressBar.IsIndeterminate <- true     

        let doBusyAsync progress operation =  
            progress
            async
                {   
                  do! operation
                }
            |> Async.StartImmediate 
    
        let onThreadPool operation =
            async
                {    
                  let context = System.Threading.SynchronizationContext.Current
                  do! Async.SwitchToThreadPool()
                  let! result = operation
                  do! Async.SwitchToContext context
                  return result
                } 
    
        let asyncOperation progress operation =   
            async { operation } 
            |> onThreadPool
            |> doBusyAsync progress 
    
        (progressBar(), longRunningOperation()) ||> asyncOperation 
      
    do
        //....some code....
        this.Button.Click.Add ButtonClick
asynchronous f# fsxaml
2021-11-23 23:13:28
2

最好的答案

3

有一些东西错了你的代码。

  • 第一, progressBar(), longRunningOperation() 实际上,你呼叫的长期操作和使它得到在这里运行。 (只要我能猜测你的不完全示例中,这是只是一个功能的电话,而不是另一个异步操作)。

  • 你然后通过的结果 operationprogress 周围,但这些只是 unit 值,实际上不做任何事情。

  • 因此,异步操作 async { operation } 那你过来 onThreadPool 并不做任何事情。

  • doBusyAsync你使用 Async.StartImmediate 运行作一个阻挡的方式(所以这块线,甚至如果它运行的某些实际操作)。

  • 除了被阻断,你也不需要 async { do! operation } 因为这等同于只是 operation.

在摘要,你的代码在某种程度上得到了方法太复杂。 你应该简化它向一些非常基本的第一步。 我没有权设置程序来试试这个,但我认为有些事情如下应该做的把戏:

let ButtonClick _ = 
  let longRunningOperation() = 
    // some long-running operation

  let asyncOperation() = async {
    // Start the progress bar here
    let context = System.Threading.SynchronizationContext.Current
    do! Async.SwitchToThreadPool()
    let result = longRunningOperation()
    do! Async.SwitchToContext context
    // Display the 'result' in your user interface
    // Stop the progress bar here
  }

  Async.Start(asyncOperation)

我删除所有无用功能和参数通过,并简化它尽可能多-这只是你的长期运行的操作,这是直接从 async 一旦它开到线的游泳池。 你得到你的结果之后,切换回原来的上下文中,应该能够显示,在用户接口。 理想的情况下,你会做的 longRunningOperation 本身异(并呼吁它使用 let!)但上述应工作。

2021-11-24 00:15:43
0

总结一事,我已延长Tomáš Petříček的代码代码相关的长期运行的操作的基础上吉姆冶的评论(大约跳回UI上的螺纹)。 代码现在就像一个特色。 我感谢托马Petříček为他的种类和详细的回答。

    let low = string (this.TextBox2.Text)
    let high = string (this.TextBox3.Text)
    let path = string (this.TextBox4.Text)

    (* longRunningOperation() replaced by textBoxString4() and textBoxString3() 
       based on the comment by Jim Foye
    
    let longRunningOperation() = 
        async
            {
              match textBoxString4 low high >= 0 with
              | false -> this.TextBox1.Text <- textBoxString3 low high path 
              | true  -> this.TextBox1.Text <- "Chybný rozdíl krajních hodnot"        
            }
    *)

    let textBoxString4() = 
        async
            {
              let result = textBoxString4 low high
              return result
            }                  
                           
    let textBoxString3() =        
        async
            {
              //the actual long running operation (reading data 
              //from Google Sheets)
              let result = textBoxString3 low high path 
              return result
            }  

    let asyncOperation() = 
        async
            {
              let context = System.Threading.SynchronizationContext.Current
              this.ProgressBar2.IsIndeterminate <- true
              do! Async.SwitchToThreadPool()
              (*let! result = longRunningOperation() throws an exception 
              "The calling thread cannot access this object because
               a different thread owns it." 
              *)
              let! result4 = textBoxString4()  
              let! result3 = textBoxString3()  
              do! Async.SwitchToContext context
              match result4 >= 0 with
              | false -> this.TextBox1.Text <- result3
              | true  -> this.TextBox1.Text <- "Chybný rozdíl krajních hodnot" 
              this.ProgressBar2.IsIndeterminate <- false
            } 
    Async.StartImmediate(asyncOperation())//not working with Async.Start
                                             
2021-11-24 18:29:36

其他语言

此页面有其他语言版本

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................