Update UI async?

前端 未结 3 658
故里飘歌
故里飘歌 2021-01-13 19:28

Consider this example:

Private Sub Button_Click(
    sender As Button, e As RoutedEventArgs) Handles btn.Click

  sender.IsEnabled = False

  Thread.Sleep(50         


        
3条回答
  •  日久生厌
    2021-01-13 19:53

    Instead of creating a thread of your own you can also use the BackgroundWorker Control. By calling the Method "RunWorkerAsync" the DoWork Event get's called in another Thread.

    By Calling the Method "CancelAsync" form your UI thread you can set the Backgroundworker to "Cancellation Pending" (Property of the Control "CancellationPending" is then true). In your long running background thread you can check for that property (e.g. if you have a loop: exit the loop as soon as CancellationPending is true). This is a quite nice feature to safely abort the thread.

    In addition with the Backgroundworker you can also report the progress of the thread (e.g. for use in a ProgressBar)

    Example:

    Public Class Form1
    
       Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    
          '** Set to true if you want the ReportProgress Event
          BackgroundWorker1.WorkerReportsProgress = True
          BackgroundWorker1.WorkerSupportsCancellation = True
       End Sub
    
       Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    
          Dim i As Integer
          Dim n As Integer = 100
          Dim iLastPerc As Integer
    
    
          While Not BackgroundWorker1.CancellationPending AndAlso i < n
    
             '** Do your time consuming actions here
             Threading.Thread.Sleep(500)
    
             If Math.Floor((i / n) * 100) > iLastPerc Then
                '** If the Progress has changed. Report
                iLastPerc = CInt(Math.Floor((i / n) * 100))
                BackgroundWorker1.ReportProgress(iLastPerc)
             End If
    
             i += 1
          End While
    
       End Sub
    
       Private Sub btnStart_Click(sender As System.Object, e As System.EventArgs) Handles btnStart.Click
    
          '** Run the Backgroundworker
          BackgroundWorker1.RunWorkerAsync()
    
       End Sub
    
       Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    
          '** Update the ProgressBar
          ProgressBar1.Value = e.ProgressPercentage
    
       End Sub
    
       Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    
          '** Worker is done. Check for Exceptions or evaluate the Result Object if you like
    
       End Sub
    
       Private Sub btnCancel_Click(sender As System.Object, e As System.EventArgs) Handles btnCancel.Click
    
          '** Cancel the worker
          BackgroundWorker1.CancelAsync()
    
          MsgBox("Finished!")
    
       End Sub
    End Class
    

    In reference to your question the code should be:

    Private Sub btn_Click(sender As Button, e As RoutedEventArgs) Handles btn.Click
      sender.IsEnabled = False
      Using bw As New BackgroundWorker()
        AddHandler bw.DoWork, Sub(s, ea) Thread.Sleep(5000)
        AddHandler bw.RunWorkerCompleted, Sub(s, ea) sender.IsEnabled = True
        bw.RunWorkerAsync()
      End Using
    End Sub
    

提交回复
热议问题