如何从 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)
我正在使用文件流读取二进制文件,并且正在使用异步等待以避免冻结 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)