Pokrok bar s async v FsXaml aplikácie

0

Otázka

V mojom F# (FsXaml/Kód Pozadu) žiadosť, by som chcel použiť pokrok bar bez využitie pozadí pracovník, ako som si v C#. Na základe článku na internet (odkaz tu), snažil som sa používať asynchrónnym pracovných postupov.

Vytvoril som kód na základe (na niektoré rozšíriť) na príklady v uvedenom článku, ale to nie je práca ako som očakával. Aktuálne vlákno (UI vlákno) je stále blokované ako keby č async kód bol tam. Žiadny prechod na pozadí niť sa vyskytuje. Na indikačnej lište sa aktivuje len po dlhý beh prevádzky bolo hotové. Odstránenie onThreadPool funkcia nemá žiadny vplyv.

Moja otázka je: Čo je zlé v mojom kóde a ako na to právo?

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

Najlepšiu odpoveď

3

Existuje niekoľko vecí, zle sa s vaším kódom.

  • Po prvé, v progressBar(), longRunningOperation() ste vlastne volať dlho beží prevádzka a tak sa to všetko dostane spustiť tu. (Ako ďaleko, ako len môžem hádať z vášho neúplné vzorky, to je len volanie funkcie, nie je ďalšie asynchrónne operácie).

  • Potom môžete prejsť výsledky operation a progress okolo, ale tie sú len unit hodnoty, ktoré nie sú v skutočnosti nič robiť.

  • Z toho vyplýva, asynchrónne operácie async { operation } že ste prejsť na onThreadPool nie je to vôbec nič.

  • V doBusyAsyncpoužívate Async.StartImmediate ak chcete spustiť prevádzku blokuje cestu (tak to by bloku nite, aj keď to bolo spustené niektoré skutočnej prevádzky).

  • Okrem toho je blokovanie, môžete tiež nie je potrebné async { do! operation } pretože to je ekvivalentné len operation.

V súhrne, váš kód nejako dostal príliš zložité. Mali by ste si zjednodušiť ho niečo veľmi základné ako prvý krok. Nemám právo setup to skúsiť, ale myslím, že niečo ako tieto by mali stačiť:

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)

Odstránil som všetky zbytočné funkcie a parametrov absolvovanie a zjednodušené to toľko, ako je to možné - to je len vaše dlhý beh operácia, ktorá sa nazýva priamo z async raz sa prepne na niť bazén. Dostanete svoj výsledok a po prepnutí späť do pôvodného kontextu, by mal byť schopný zobrazovať vo vašom používateľskom rozhraní. V ideálnom prípade, by ste, aby longRunningOperation sám asynchrónne (a hovoru pomocou let!) ale vyššie uvedené, by mali pracovať.

2021-11-24 00:15:43
0

Súčet veci, až som sa rozšírili Tomáš Petříček kódu s kódom vzťahujúce sa na dlhý beh prevádzky na základe Jim Foye komentár (o poskakovanie späť na UI vlákno). Kód teraz funguje ako kúzlo. Moja vďaka Tomáš Petříček na jeho druh a podrobnú odpoveď.

    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

V iných jazykoch

Táto stránka je v iných jazykoch

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