当函数 return 为真时引发事件
Raise Event when a Function return True
我正在修改的部分程序涉及使用专有库通过串行端口进行通信。不幸的是,这个库没有 System.IO.Ports 命名空间包含的 SerialPort.DataReceived event。事实上,它没有任何事件,但是它确实有两个可以类似使用的函数:
Port.WaitForData(整数时间)
此函数等待给定的时间以通过端口接收一些先前指定的字符串。 returns 1 表示 是,收到字符串 ,或 0 表示 否,未收到字符串,超时。
Port.IsReceiveBufferEmpty()
此函数returns一个布尔值是,接收缓冲区为空或否,接收缓冲区包含数据 .
在我看来,我必须创建一些线程,以便在端口打开时不断循环,并执行以下两项操作之一:
对于每个循环,调用 WaitForData(某个大数字)并将它正在寻找的指定字符串设置为“”,或 vbCrLf,或其他我可以确认它会在每次数据是发送。如果发现平滑,请阅读并写入文本框。如果 WaitForData 没有找到任何东西,再次循环。
对于每个循环,调用 IsReceiveBufferEmpty(),如果不是,则读取它并写入文本框。
实现它的最佳方法是什么?第一个选项对我来说似乎可能更有效,尽管我对这些方法在幕后如何工作几乎一无所知。显然我想在执行此操作时保持我的表单响应,那么我应该如何在不冻结表单但能够读取任何传入数据的情况下连续循环?
感谢您的帮助。
也许不是最优雅的解决方案,但您可以使用 BackgroundWorker
来执行 IO。例如像这样的伪代码:
Public Class MyForm
Private _port As ProprietaryIOLibrary
Private WithEvents Worker As System.ComponentModel.BackgroundWorker
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
_port = New ProprietaryIOLibrary()
Worker = New System.ComponentModel.BackgroundWorker()
Worker.WorkerReportsProgress = True
Worker.WorkerSupportsCancellation = True
Worker.RunWorkerAsync()
End Sub
Private Sub ButtonCancel_Click(sender As Object, e As EventArgs) Handles ButtonCancel.Click
Worker.CancelAsync()
End Sub
Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
Do
If _port.WaitForData(1000) Then ' Adjust timeout depending on cancel responsiveness?
Dim data As String = _port.ReadDataAsString() ' ?
' Trigger the ProgressChanged event, passing the data
Worker.ReportProgress(0, data)
End If
If Worker.CancellationPending Then
Exit Do
End If
Loop
End Sub
Private Sub Worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles Worker.ProgressChanged
' Update the UI with the data received
' ProgressChanged is called on the UI thread, so no need to Invoke
Dim data As String = DirectCast(e.UserState, String)
TextBox1.Text &= data & vbCrLf
End Sub
Private Sub Worker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles Worker.RunWorkerCompleted
TextBox1.Text &= "Complete!"
End Sub
End Class
我正在修改的部分程序涉及使用专有库通过串行端口进行通信。不幸的是,这个库没有 System.IO.Ports 命名空间包含的 SerialPort.DataReceived event。事实上,它没有任何事件,但是它确实有两个可以类似使用的函数:
Port.WaitForData(整数时间)
此函数等待给定的时间以通过端口接收一些先前指定的字符串。 returns 1 表示 是,收到字符串 ,或 0 表示 否,未收到字符串,超时。
Port.IsReceiveBufferEmpty()
此函数returns一个布尔值是,接收缓冲区为空或否,接收缓冲区包含数据 .
在我看来,我必须创建一些线程,以便在端口打开时不断循环,并执行以下两项操作之一:
对于每个循环,调用 WaitForData(某个大数字)并将它正在寻找的指定字符串设置为“”,或 vbCrLf,或其他我可以确认它会在每次数据是发送。如果发现平滑,请阅读并写入文本框。如果 WaitForData 没有找到任何东西,再次循环。
对于每个循环,调用 IsReceiveBufferEmpty(),如果不是,则读取它并写入文本框。
实现它的最佳方法是什么?第一个选项对我来说似乎可能更有效,尽管我对这些方法在幕后如何工作几乎一无所知。显然我想在执行此操作时保持我的表单响应,那么我应该如何在不冻结表单但能够读取任何传入数据的情况下连续循环?
感谢您的帮助。
也许不是最优雅的解决方案,但您可以使用 BackgroundWorker
来执行 IO。例如像这样的伪代码:
Public Class MyForm
Private _port As ProprietaryIOLibrary
Private WithEvents Worker As System.ComponentModel.BackgroundWorker
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
_port = New ProprietaryIOLibrary()
Worker = New System.ComponentModel.BackgroundWorker()
Worker.WorkerReportsProgress = True
Worker.WorkerSupportsCancellation = True
Worker.RunWorkerAsync()
End Sub
Private Sub ButtonCancel_Click(sender As Object, e As EventArgs) Handles ButtonCancel.Click
Worker.CancelAsync()
End Sub
Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
Do
If _port.WaitForData(1000) Then ' Adjust timeout depending on cancel responsiveness?
Dim data As String = _port.ReadDataAsString() ' ?
' Trigger the ProgressChanged event, passing the data
Worker.ReportProgress(0, data)
End If
If Worker.CancellationPending Then
Exit Do
End If
Loop
End Sub
Private Sub Worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles Worker.ProgressChanged
' Update the UI with the data received
' ProgressChanged is called on the UI thread, so no need to Invoke
Dim data As String = DirectCast(e.UserState, String)
TextBox1.Text &= data & vbCrLf
End Sub
Private Sub Worker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles Worker.RunWorkerCompleted
TextBox1.Text &= "Complete!"
End Sub
End Class