当函数 return 为真时引发事件

Raise Event when a Function return True

我正在修改的部分程序涉及使用专有库通过串行端口进行通信。不幸的是,这个库没有 System.IO.Ports 命名空间包含的 SerialPort.DataReceived event。事实上,它没有任何事件,但是它确实有两个可以类似使用的函数:

  1. Port.WaitForData(整数时间)

    此函数等待给定的时间以通过端口接收一些先前指定的字符串。 returns 1 表示 是,收到字符串 ,或 0 表示 否,未收到字符串,超时

  2. Port.IsReceiveBufferEmpty()

    此函数returns一个布尔值是,接收缓冲区为空否,接收缓冲区包含数据 .

在我看来,我必须创建一些线程,以便在端口打开时不断循环,并执行以下两项操作之一:

  1. 对于每个循环,调用 WaitForData(某个大数字)并将它正在寻找的指定字符串设置为“”,或 vbCrLf,或其他我可以确认它会在每次数据是发送。如果发现平滑,请阅读并写入文本框。如果 WaitForData 没有找到任何东西,再次循环。

  2. 对于每个循环,调用 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