Bara de progres cu async în FsXaml cerere

0

Problema

În F# (FsXaml/Cod Spatele) aplicarea, aș dori să utilizați o bară de progres, fără utilizarea de un lucrător fundal ca sa fac in C#. Bazat pe un articol de pe internet (link-ul este aici), am încercat să folosesc asincron fluxuri de lucru.

Am creat codul de baza (pentru a extinde unele) pe exemplele din articolul menționat anterior, dar nu a mers ca am avut de asteptat. Firul curent (UI fir) este încă blocat ca daca nu async cod a fost acolo. Nici o comutare de la un fir de fundal apare. Bara de progres este activat numai după lungă de funcționare operațiunea a fost terminat. Eliminarea onThreadPool funcție nu are nici un efect.

Intrebarea mea este: Ce este greșit în codul meu și cum să facă dreapta pe ea?

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

Cel mai bun răspuns

3

Există o serie de lucruri în neregulă cu codul.

  • În primul rând, în progressBar(), longRunningOperation() te sun de fapt lungă de funcționare funcționare și, astfel, totul se derula aici. (În măsura în care eu pot ghici din incomplete eșantion, aceasta este doar un apel de funcție, nu o altă operație asincronă).

  • Apoi trece rezultatele operation și progress în jurul valorii de, dar acestea sunt doar unit valori care nu face de fapt nimic.

  • În consecință, operațiunea asincron async { operation } de onThreadPool nu face nimic, la toate.

  • În doBusyAsync, puteți utiliza Async.StartImmediate pentru a rula funcționarea în blocarea fel (deci, acest lucru va bloca firul, chiar dacă acesta a fost difuzate unele funcționarea reală).

  • În afară de a fi blocarea, de asemenea, nu trebuie async { do! operation } deoarece acest lucru este echivalent cu doar operation.

În rezumat, codul ajuns cumva mult prea complex. Tu ar trebui să simplifice la ceva foarte de bază, ca prim pas. Nu au dreptul de configurare pentru a încerca acest lucru, dar cred că ceva de genul următor ar trebui să facă truc:

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)

Am scos toate funcții inutile și parametru trece și simplificate cât mai mult posibil - este doar o funcționare de lungă de funcționare, care este numit direct de la async odată ce se trece la thread pool. Veți obține rezultatul dvs. și, după trecerea înapoi la original context, ar trebui să fie capabil să afișeze în interfața cu utilizatorul. În mod ideal, ar face longRunningOperation în sine asincron (și apel folosind let!) dar cele de mai sus ar trebui să funcționeze.

2021-11-24 00:15:43
0

Pentru a rezuma lucrurile, am extins Tomáš Petříček cod cu codul legate de lungă de funcționare funcționare bazat pe Jim Foye comentariu (despre țopăit înapoi pe firul UI). Codul acum funcționează ca un farmec. Mulțumirile mele Tomáš Petříček pentru neamul lui și răspuns detaliat.

    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

În alte limbi

Această pagină este în alte limbi

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