ความคืบหน้าบาร์กับ async ใน FsXaml องโปรแกรม

0

คำถาม

ในของฉัน 'F'# (FsXaml/รหัสหลัง) โปรแกรม,ฉันต้องการจะใช้ความคืบหน้าโดยไม่มีบาร์ที่ utilisation ของพื้นหลังของงานที่ผมทำใน C#. จากบทความเกี่ยวกับอินเตอร์เน็ต(การเชื่อมต่อ อยู่)ฉันพยายามจะใช้ asynchronous workflows.

ฉันสร้างรหัสจาก(จะมีขยาย)บนตัวอย่างใน aforementioned บทความแต่มันไม่ได้ทำงานที่ฉันคาดไว้เลย ดเธรดปัจจุบัน(ส่วนติดต่อผู้ใช้ด้าย)ยังคงถูกปิดกั้นเหมือนว่าไม่ async รหัสอยู่ที่นั่น ไม่มีการสลับผังต้องเป็นพื้นหลังของเธรดเกิดขึ้น. ที่ต้องเดินหน้าต่อร์บาร์เปิดใช้งานเดียวหลังจากที่นานกำลังปฏิบัติการถูกเสร็จสิ้นแล้ว ลบที่ 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() คุณโทรหานานกำลังปฏิบัติการและทุกอย่างมันจะวิ่งอยู่ที่นี่ (เท่าที่ฉันสามารถเดาออกจากยังไม่สมบูรณ์ตัวอย่างนี่มันเป็นแค่การเรียกฟังก์ชันไม่ใช่อีก asynchronous ปฏิบัติการ).

  • คุณนั้นส่งผลลัพธ์ operation แล้ว progress แต่พวกนั้นเป็นแค่ unit ค่ามันไม่จริงทำอะไรเลย

  • ดังนั้นค asynchronous ปฏิบัติการ async { operation } ที่คุณผ่านไป onThreadPool ไม่ได้ทำอะไรเลย

  • ใน doBusyAsyncคุณใช้ Async.StartImmediate ต้องไปลองปฏิบัติการในการปิดกั้นทาง(ดังนั้นมันจะบล็อกด้าถึงแม้ว่ามันจะเป็นการแท้จริงปฏิบัติการ).

  • นอกจากเป็นการปิดกั้นคุณก็ไม่ต้องการ async { do! operation } เพราะนี่คือมพล่ามคำเชยๆออกมาไม่หยุดแค่ operation.

ในรายงานสรุปของคุณรหัสบางอย่างมีทางเหมือนกัที่ซับซ้อน คุณควรจะ simplify มันต้องบางอย่างมากพื้นฐานเป็นก้าวแรกไปก่อน ฉันไม่มีที่ถูกต้องตั้งค่าที่จะลองเรื่องนี้แต่ฉันคิดว่ามีบางอย่างเหมือนคอยตามควรทำเทคนิค:

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)

ฉันถูกเอาออกทั้งไร้ประโยชน์ฟังก์ชันและพารามิเตอร์ผ่านไปและประยุกต์@item text character set มันให้มากที่สุดเท่าที่จะทำได้-มันเป็นแค่ของคุณนานกำลังปฏิบัติการซึ่งเป็นชื่อโดยตรงจาก async ครั้งนึงมัน switches เพื่อเธรดสร้างสระว่ายน้ำ คุณเอาของคำตอบของคุณและหลังจากเปลี่ยนกลับไปที่ต้นฉบับคอนเท็กซ์น่าจะเป็นสามารถแสดงที่อยู่ของผู้ใช้ส่วนติดต่อ. เข้าท่าดีนิเราจะทำทุกอย่างที่เราทำเธอจะทำ longRunningOperation ตัวมันเอง asynchronous(และรอจนกว่าผมจะเรียกใช้ let!แต่ที่เหนือควรจะทำงานแล้ว

2021-11-24 00:15:43
0

เพื่อผลรวมเรื่องขึ้นฉันมีส่วนขยายเพิ่มเติม Tomáš Petříček เป็นรหัสกับรหัสที่เกี่ยวข้องกับนานกำลังปฏิบัติการจากจิม Foye เป็นความคิดเห็น(เรื่องโดกลับส่วนติดต่อผู้ใช้ด้าย). รหัสผ่านนี้ได้ผมเหมือนมนต์สะกด. ฉันต้องขอบคุณ Tomáš 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ý
..................................................................................................................