VB. net serialport.readline против получаемых данных против потоковой передачи - PullRequest
0 голосов
/ 14 июля 2020

Начинающий (очень новичок) программист, работающий в VB. net ... Я читал много разных мнений по этому поводу, нарезка швов была бы лучшим решением, но на данный момент это немного выше моей головы. То, что я пытаюсь выполнить sh, - это чтение строки данных из последовательного порта (Bluetooth). Длина данных всегда одинакова и всегда заканчивается CRLF (данные - ASCII). Я читаю данные с цифрового динамометрического ключа, пользователь должен затянуть 6 болтов гаечным ключом, каждый болт отправляет строку данных через последовательный порт. Я читаю эти необработанные данные, извлекаю из строки фактическое значение крутящего момента и сохраняю его в базе данных. У меня работает соединение с базой данных, я могу читать данные и извлекать нужное значение. Проблема в том, что если пользователю по какой-то причине необходимо прекратить чтение, я не могу выйти из мероприятия. Я попытался добавить кнопку, которая устанавливает для переменной значение true (Dim BoolEscape as Boolean в значение «True»). Затем добавил вызов Application.DoEvents () с последующей проверкой, чтобы убедиться, что BoolEscape = True, затем выйдите из подпрограммы ... Из того, что я прочитал, это не работает и никогда не будет.

Полученная строка данных форматируется: "RE, 001,100.0,16 / 08 / 20,12: 45: 10CRLF"

Ниже приведен код из моего события BtnStartRead_Click ... Я показываю только 2 болта, потому что оно просто повторяется ... . Я считаю, что многопоточность - это ответ, но опять же, не понимаю, как это работает ....

 Private Sub btnStartRead_Click(sender As Object, e As EventArgs) Handles btnStartRead.Click
    On Error GoTo err_handle
    boolEscape = False
    txtBolt1.BackColor = Color.FromArgb(255, 255, 128)
    txtBolt2.BackColor = Color.FromArgb(255, 255, 128)
    txtBolt3.BackColor = Color.FromArgb(255, 255, 128)
    txtBolt4.BackColor = Color.FromArgb(255, 255, 128)
    txtBolt5.BackColor = Color.FromArgb(255, 255, 128)
    txtBolt6.BackColor = Color.FromArgb(255, 255, 128)
    lblA1.Visible = True
    ShowRXon()
    txtRaw1.Text = mySerialPort.ReadLine
    ShowRXoff()
    txtBolt1.Text = txtRaw1.Text.Substring(7, 4)
    If checkValue(txtBolt1.Text) = False Then
        txtBolt1.BackColor = Color.Red
    End If
    lblA1.Visible = False
    lblA2.Visible = True

    Application.DoEvents()
    If boolEscape = True Then
        MsgBox("You have STOPPED the measurment logging...", vbOKOnly)
        boolEscape = False
        Exit Sub
    End If

    ShowRXon()
    txtRaw2.Text = mySerialPort.ReadLine
    ShowRXoff()
    txtBolt2.Text = txtRaw2.Text.Substring(7, 4)
    If checkValue(txtBolt2.Text) = False Then
        txtBolt2.BackColor = Color.Red
    End If
    lblA2.Visible = False
    lblA3.Visible = True

    Application.DoEvents()
    If boolEscape = True Then
        MsgBox("You have STOPPED the measurment logging...", vbOKOnly)
        boolEscape = False
        Exit Sub
    End If

Как бы я go мог добавить это в отдельный поток или указать событие получения данных a лучше подход, чтобы линия всегда была одинаковой длины и всегда заканчивалась CRLF ... и если да, то как холодно я модифицирую ее, чтобы использовать это вместо этого.

1 Ответ

1 голос
/ 15 июля 2020

Вообще говоря, вы должны обрабатывать событие DataReceived из SerialPort. Вы можете инициировать любой процесс, который вам нравится, в событии Click вашего Button, но это только инициация. Событие DataReceived будет вызвано, когда ваш объект SerialPort получит данные, а затем вы обработаете эти данные. Если вы ожидаете получить одну строку данных шесть раз, вы можете вызвать ReadLine в обработчике событий, и событие, вероятно, будет сгенерировано шесть раз.

Нет необходимости инициировать какую-либо многопоточность, потому что она уже сделано за вас, т.е. событие DataReceived вызывается во вторичном потоке, поэтому ваш обработчик событий выполняется во вторичном потоке. Это означает, что вы не можете получить доступ к элементам управления непосредственно в этом обработчике событий или к любому методу, вызываемому из этого обработчика событий. Вам нужно будет маршалировать вызов потока пользовательского интерфейса, чтобы обновить пользовательский интерфейс. Вот простой пример отправки нескольких команд на SerialPort и отображения ответов:

Private commands As Queue(Of String)

Private Sub SendNextCommand()
    If commands.Any() Then
        SerialPort1.WriteLine(commands.Dequeue())
    End If
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    commands = New Queue(Of String)({"First", "Second", "Third"})

    SendNextCommand()
End Sub

Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
    Dim response = SerialPort1.ReadLine()

    'This event is raised on a secondary thread so we must marshal to the UI thread to update the UI.
    TextBox1.BeginInvoke(Sub() TextBox1.AppendText(response & Environment.NewLine))

    SendNextCommand()
End Sub
...