函数返回True时引发事件

时间:2015-07-21 17:32:23

标签: vb.net multithreading serial-port backgroundworker

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

  1. Port.WaitForData(int time)

    此函数等待给定的时间量,以便通过端口接收一些先前指定的字符串。它为是,收到字符串返回1,为 no返回0,没有收到字符串,超时

  2. Port.IsReceiveBufferEmpty()

    此函数返回是的布尔值,接收缓冲区为空否,接收缓冲区包含数据

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

    1. 对于每个循环,使用指定的字符串调用WaitForData(一些大数字),它将设置为""或vbCrLf,或者其他我可以确认它将在每次收到的内容数据已发送。如果它找到了smoething,请阅读它并写入文本框。如果WaitForData找不到任何内容,请再次循环。

    2. 对于每个循环,调用IsReceiveBufferEmpty(),如果不是,请读取并写入文本框。

    3. 实施此方法的最佳方法是什么?第一个选项对我来说似乎更有效,尽管我几乎都不知道这些方法是如何工作的。显然,我希望在执行此操作时保持表单响应,那么如何在不冻结表单但是能够读取任何传入数据的情况下继续循环?

      感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

也许不是最优雅的解决方案,但您可以使用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