如何从 async await sub 更新 label.text?

How to update label.text from async await sub?

我正在使用文件流读取二进制文件,并且正在使用异步等待以避免冻结 UI

Await Task.Run(Sub()
 For i = 0 To file_len Step 512
   fs.Seek(i, SeekOrigin.Begin)       ' look into the next 4096 of the file
   fs.Read(array_for_fat, 0, 512)             ' read it to the buffer
   label2.text = i                      'getting the error here
  Next
 End Sub)

问题是我无法更新(我想更新有关应用程序已读取多少的信息)

label2.text = i

来自这个话题

请提供任何解决方案,如何从 async-await sub 更新文本框,或者我可以使用更适合我目的的东西? 完整代码示例:

Private Async Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click

        OpenFileDialog1.FileName = ".bin file"
        If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
            Label9.Text = System.IO.Path.GetFullPath(OpenFileDialog1.FileName)
        Else
            Exit Sub
        End If

        file_len = New System.IO.FileInfo(Label9.Text).Length.ToString
       If Label9.Text.Contains(".bin") Or Label9.Text.Contains(".BIN") Then
        Else
            Label9.Text = ""
       End If
        Using fs As New FileStream(Label9.Text, FileMode.Open, FileAccess.Read, FileShare.None)
      
            Await Task.Run(Sub()
               For i = 0 To file_len Step 512
                 fs.Seek(i, SeekOrigin.Begin)       ' look into the next 4096 of the file
                 fs.Read(array_for_fat, 0, 512)             ' read it to the buffer
                
              For Each position In Form1.Locate(array_for_fat, bytesToFind)
                    If array_for_fat(0) <> 1 Or array_for_fat(52) <> &H41 Then Continue For                
    'searching for proper data in the 512byte dump from file
                      i = file_len   'stop reading the file when found the dump we need
                       For b = 28 To 100 Step 2
                      If array_for_fat(b) = 0 Then                                                                                                         ' found? execute
                       Exit For
                      End If
                      result &= array_for_fat(b).ToString("X") & array_for_fat(b + 1).ToString("X")
                       Next
                      Exit For
                       Next
                Next
             End Sub)
 end using
end sub

和定位子代码(在字节数组中搜索字节模式):

Public Function Locate(ByVal self As Byte(), ByVal candidate As Byte()) As Integer()
  If IsEmptyLocate(self, candidate) Then Return Empty
  Dim list = New List(Of Integer)()

 For i As Integer = 0 To self.Length - 1
    If Not IsMatch(self, i, candidate) Then Continue For
    list.Add(i)
 Next

 Return If(list.Count = 0, Empty, list.ToArray())
End Function

Public Function IsEmptyLocate(ByVal array As Byte(), ByVal candidate As 
  Byte()) 
     As Boolean
    Return array Is Nothing OrElse candidate Is Nothing OrElse array.Length = 
     0 OrElse candidate.Length = 0 OrElse candidate.Length > array.Length
 End Function

Public Function IsMatch(ByVal array As Byte(), ByVal position As Integer, 
 ByVal candidate As Byte()) As Boolean
If candidate.Length > (array.Length - position) Then Return False

For i As Integer = 0 To candidate.Length - 1
    If array(position + i) <> candidate(i) Then Return False
Next

Return True

结束函数

查看 How to: Make thread-safe calls to Windows Forms controls 了解更多详情。

label2.text = i 替换为此调用(来自文章):

Private Sub WriteTextSafe(ByVal value As String)
    If label2.InvokeRequired Then
        Dim d = New SafeCallDelegate(AddressOf WriteTextSafe)
        label2.Invoke(d, New Object() {value})
    Else
        label2.Text = value
    End If
End Sub

另一个例子:

''' <summary>
''' Thead-safe add value to list.
''' </summary>
''' <param name="value">The value.</param>
Private Sub UpdateLabel2(value As String)
    If label2.InvokeRequired Then
        label2.Invoke(Sub() label2.Text = value)
    Else
       label2.Text = value
    End If
End Sub

提示:通过 naming 您的控件和变量,然后是 label1、label2,使您的 coding-life 减少 error-prone。一年多以后,当你 return 看到这段代码时,你会记得 label1 是什么而不用看表格吗?

你可以使用 Progress(Of T)

Dim progress As IProgress(Of Integer) = New Progress(Of Integer)(Sub (value as Integer) label2.Text = value)
Await Task.Run(Sub()
 For i = 0 To file_len Step 512
   fs.Seek(i, SeekOrigin.Begin)
   fs.Read(array_for_fat, 0, 512)
   progress(i)
  Next
 End Sub)