Форум программистов, компьютерный форум, киберфорум
Visual Basic .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342

Почему пропадают/искажаются сообщения SerialPort?

06.03.2025, 17:09. Показов 7626. Ответов 61

Студворк — интернет-сервис помощи студентам
Программа должна обмениваться данными с несколькими платами Arduino(сейчас подключаю 3 шт., планируется больше, но проблемы появляются и ни одной шт., и на двух…).
В тестовом режиме режиме я отправляю “99/0/0/0” – плата считывает это сообщение и отправляет обратно. В мониторе порта программы Arduino все работает четко и стабильно, без каких-либо сбоев (во всяком случае, мне не удалось такое обнаружить).
Но вот когда подключаю написанную программу – начинаются проблемы:
часто вместо отправленного сообщения программа получает не отображаемые символы, в кодировке Asc номера: 13, 10. Иногда программа вообще не получает никакого ответа.
В программе использованы библиотеки:
VB.NET
1
2
3
4
5
6
Imports System.IO.Ports
Imports System.Threading
Imports System.Runtime.InteropServices
Imports System.Windows.Forms.Design
Imports System.IO
Imports System.Text
Программа формирует коллекцию COM-портов:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
Public oNameCol As New Dictionary(Of [String], [String])() ' массив СОМ-портов с номерами ответов плат
Public oNunbCol As New Dictionary(Of [String], [String])() ' массив номеров плат с СОМ-портами
Public oNPlat As Integer = 0 '  счетчик количества подключенных плат 
Public oComPort As New List(Of SerialPort) ' коллекция СОМ-портов
Public oComSpeed As Integer = 250000 ' скорость сомпорта
Public oReadCom As String ' переменная для чтения ответа из COM-порта
Dim WithEvents mySerialPort As SerialPort
 
    Private Sub ButtR_Click(sender As System.Object, e As System.EventArgs) Handles ButtR.Click
        ReadNameCom()
     End Sub
 
    Private Sub ReadNameCom()
        Dim oPorts As String() = SerialPort.GetPortNames()
        oNPlat = 0
        oNameCol.Clear()
        oNunbCol.Clear()
        If oComPort.Count > 0 Then
            Try
                For i = 0 To oComPort.Count - 1
                    oComPort(i).Close()
                Next
            Catch ex As Exception
            End Try
        End If
        oComPort.Clear()
        For Each oName In oPorts
            If oName <> "COM1" Then
                Try
                    Try
                        Try
                            mySerialPort.Close()
                        Catch ex3 As Exception
                        End Try
                        mySerialPort = New SerialPort(oName)
                        With mySerialPort
                            .BaudRate = oComSpeed '57600 '9600
                            .Parity = Parity.None
                            .StopBits = StopBits.One
                            .DataBits = 8
                            .Handshake = Handshake.None
                            .RtsEnable = True
                            .Open()
                        End With
                    Catch ex As Exception
                    End Try
                    oReadCom = ""
                    mySerialPort.WriteLine("97/0/0/0")
                    Thread.Sleep(90)
                    oReadCom = mySerialPort.ReadExisting()
                    If oReadCom = "" Then
                        Thread.Sleep(50)
                        oReadCom = mySerialPort.ReadExisting()
                    End If
                    mySerialPort.Close()
                Catch ex2 As Exception
                End Try
                If oReadCom <> "" Then
                    oNameCol.Add(oName, oReadCom) 
                    oNunbCol.Add(oReadCom, oName) 
                    oNPlat = oNPlat + 1
                End If
            End If
        Next
        Try
            If oNunbCol.Count > 0 Then
                For i = 1 To oNunbCol.Count
                    If oNunbCol.ContainsKey(i.ToString) Then
                        ListBox1.Items.Add(i.ToString & "  -  " & oNunbCol(i.ToString))
                        oComPort.Add(New SerialPort(oNunbCol(i.ToString)))
                        With oComPort(i - 1) ' нумерация от 0
                            .BaudRate = oComSpeed '57600
                            .Parity = Parity.None
                            .StopBits = StopBits.One
                            .DataBits = 8
                            .Handshake = Handshake.None
                            .RtsEnable = True
                        End With
                    Else
                    End If
                Next
            End If
        Catch ex As Exception
            ButtR.BackColor = Color.Red
        End Try
    End Sub
Провожу тест в цикле:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    Private Sub ButStart_Click(sender As System.Object, e As System.EventArgs) Handles ButStart.Click
            For i = 1 To 100
                    SubStart()
            Next
    End Sub
 
    Private Sub SubStart()
        Dim oText As String = ""
        oText = ComsRead() ' ОТПРАВКА ЗАПРОСА
        Debug.Print(oText)
    End Sub
 
    Public oActivText As String ' переменная содержит последний ответ полученный в событии COM-порта
 
    Function ComsRead() As String ' функция отправки и получения ответа из COM-порта
        ComsRead = ""
        Try
            Dim oCallP2 As Integer = 1 ' номер платы чтения сигнала
            Dim oMess1 As String ' тест сообщения в COM-порт подачи сигнала
            oActivText = ""
            AddHandler oComPort(oCallP2).DataReceived, AddressOf DataReceivedHandler ' включение события 
            If oCallP2 = 1 Then
                oMess1 = "99/0/0/0"
                oComPort(oCallP2).WriteLine(oMess1)
            End If
            Dim oText As String = ""
            Thread.Sleep(5)
            For i = 1 To 50
                Thread.Sleep(10)
                oText = oActivText
                If oText <> "" Then
                    i = 999
                End If
            Next i
            RemoveHandler oComPort(oCallP2).DataReceived, AddressOf DataReceivedHandler 
            oComPort(oCallP2).DiscardInBuffer()
            If InStr(oText, "99") = 0 Then
                If oText <> "" Then ' просмотр кодов нештатных ответов
                    TextPin.Text = ""
                    For i = 1 To oText.Length
                        TextPin.Text = TextPin.Text & "  " & Asc(Mid(oText, i, 1))
                        Debug.Print(i.ToString & "=" & Asc(Mid(oText, i, 1)))
                    Next
                End If
            If InStr(oText, "99") = 0 Then
                oText = ""
                oComPort(oCallP2).Close()
                oComPort(oCallP2).Open()
                If oCallP2 = 1 Then
                    oMess1 = "99/0/0/0" 
                    oComPort(oCallP2).WriteLine(oMess1)
                End If
                Thread.Sleep(100) 
                oText = oComPort(oCallP2).ReadExisting()
                If oText = "" Then
                    Thread.Sleep(50) 
                    oText = oComPort(oCallP2).ReadExisting()
                End If
            End If
            ComsRead = oText
        Catch ex As Exception
        End Try
    End Function
 
    Private Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs)
        Try
            Dim sp As SerialPort = CType(sender, SerialPort)
            Dim indata As String = sp.ReadExisting()
            oActivText = indata
        Catch ex As Exception
            oActivText = "Error DataReceivedHandler"
        End Try
    End Sub
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
06.03.2025, 17:09
Ответы с готовыми решениями:

Visual studio 2019. Компонент SerialPort, почему не активен, не добавляется?
Добрый день. Установил Visual studio 2019. Пишу программу для работы с последовательным портом. В примерах, ктр видел, люди перетаскивают...

Visual studio 2019. Элемент serialport, почему нет метода getportnames?
В общем установил я вижуал студио 2019 и решил накидать простую программку для работы с серийным портом но оказалось что метод с помощью...

Почему пропадают элементы в конструкторе формы?
Добрый день. Не могу понять почему пропадают элементы в конструкторе формы. Что делал до этого: У меня есть форма с необходимыми...

61
2296 / 1612 / 400
Регистрация: 26.06.2017
Сообщений: 4,774
Записей в блоге: 1
29.08.2025, 15:50
Студворк — интернет-сервис помощи студентам
Потоки чтения/записи могут завершаться после потока UI.
Позже выложу вариант, где устраню все замечания. Я примерно понимаю, где проблема.
0
Модератор
Эксперт .NET
 Аватар для Yury Komar
4372 / 3442 / 512
Регистрация: 27.01.2014
Сообщений: 6,266
29.08.2025, 18:43
Цитата Сообщение от filat18 Посмотреть сообщение
broker.Dispose()
а может ему слать CancelationToken и в потоке обрабатывать его, чтобы мягко закрыться, так сказать "изнутри", а не наглухо рубить процесс?
0
2296 / 1612 / 400
Регистрация: 26.06.2017
Сообщений: 4,774
Записей в блоге: 1
29.08.2025, 19:37
Yury Komar, а он мягко и закрывается, но есть нюанс и ТС на него попадает видимо.
0
2296 / 1612 / 400
Регистрация: 26.06.2017
Сообщений: 4,774
Записей в блоге: 1
31.08.2025, 11:12
filat18, обновлённая версия посредника.
Доработано:
- проверка сигнала завершения на любой итерации чтения/записи;
- работа с портом происходит в одном потоке;
- добавлен класс данных "запрос-ответ". Теперь каждому запросу соответствует свой ответ.
Вложения
Тип файла: zip ProtokolBroker v2.zip (15.4 Кб, 17 просмотров)
2
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
02.09.2025, 08:00  [ТС]
В v2 тоже сталкиваюсь с состоянием ступора программы, после которого Отправка перестает работать, а попытка закрыть программу не может остановить работу класса. При нажатии в VS кнопки Прервать все - оказываюсь тут:
Миниатюры
Почему пропадают/искажаются сообщения SerialPort?  
0
2296 / 1612 / 400
Регистрация: 26.06.2017
Сообщений: 4,774
Записей в блоге: 1
02.09.2025, 08:42
filat18, чуть ранее вам рекомендовали делать чтение порта используя методы Read, ReadByte или ReadChar. ReadLine ждёт символа конца строки, который, очевидно, он не получает. Кроме того у вас по видимому не настроен тайм-аут ReadTimeout.
Помимо очевидных указанных ошибок в вашем коде не видно всего того, о чём говорилось ранее в теме. А именно реализации тайм-аута ожидания ответа на запрос, контроля целостности данных и др.
Цитата Сообщение от filat18 Посмотреть сообщение
В v2 тоже сталкиваюсь с состоянием ступора программы
Как я написал выше, предоставленный мной код в этой ситуации ни при чём.
1
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
02.09.2025, 13:20  [ТС]
Uswer, благодарю за уточнения! Реализовал, в меру своего понимания - процесс существенно сдвинулся!
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
            While Not ExitSignal  ' тут может быть токен отмены
                allowReadWrite.WaitOne() ' ждём разрешения на отправку команды
 
                If ExitSignal Then
                    Exit While
                End If
 
                While (commandQueue.TryDequeue(currentCommand) = True) And (Not ExitSignal)
                    ' если команта выгружена из очереди
                    IsReadOrWrite = True ' помечаем что идёт работа с портом
 
                    ' далее сама отправка комианды в порт
#If DEBUG Then
                    _Port.WriteLine(currentCommand)
#End If
                    ' далее приём данных из порта.
                    ' Тут должна быть проверка тайм-аута ответа,
                    Thread.Sleep(1)
                    'Thread.SpinWait(900)
                    ' проверка целостности данных и т.д.
                    Dim d As Integer
                    While _Port.BytesToRead > 0
                        d = _Port.ReadByte ' принять байт из порта
                        If d <> 10 Then ' если это не конец строки
                            txt = txt + Chr(d)
                        Else ' если конец строки
                            'currentData = txt
                        End If
                    End While
#If DEBUG Then
                    'Debug.WriteLine("Reading begin")
                    If Not txt Is Nothing Then
                        If txt.Length > 1 Then
                            If InStr((txt.Length - 1), txt, "F") > 0 Then
                                currentData = Left(txt, InStr(txt, "F") - 1)
                                txt = String.Empty
                            Else
                                ' не правильный ответ
                            End If
                        End If
                    End If
                    'Debug.WriteLine("Reading end")
#End If
                    IsReadOrWrite = False
                    Answers.Enqueue(New PortBrokerData() With {.Command = currentCommand, .Answer = currentData}) ' помещаем принятые данные в очередь
 
                    If UnloadDataProc IsNot Nothing Then
                        ' неблокирующий вызов делегата
                        syncroContext.Post(UnloadDataProc, New Object)
                    End If
                    ' вариант на событии
                    'RaiseEvent DataReceived(Me, EventArgs.Empty) ' сигнальное событие о принятии данных
                End While
Но вот чего не понимаю: при заданных таймаутах чтения/записи в 5 мС, на одном чипе идет нормальное общение с временем оберации 4...5 мкС. Я для него поставил Thread.SpinWait(10) - никаких проблем опыты пока не показали!
А вот взял другой чип (с той же прошивкой и той же частотой) так его работа стабилизировалась только при Thread.Sleep(1)!?
0
2296 / 1612 / 400
Регистрация: 26.06.2017
Сообщений: 4,774
Записей в блоге: 1
02.09.2025, 16:34
Цитата Сообщение от filat18 Посмотреть сообщение
работа стабилизировалась только при Thread.Sleep(1)
Такой параметр обычно называют временем смены направления передачи данных. Эта величина зависит от железа и скорости передачи, поэтому я бы сделал его свойством брокера и устанавливал извне.
На что ещё обращаю внимание:
- запись и чтение порта будут работать только при отладке. Имейте это ввиду.
- проверку строки на Nothing и прочую обработку контроля ответа вынесите в отдельный метод или даже класс.
- вместо конкатенации строк я бы использовал StringBuilder.
1
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
04.09.2025, 07:00  [ТС]
Цитата Сообщение от Uswer Посмотреть сообщение
- запись и чтение порта будут работать только при отладке. Имейте это ввиду.
Пожалуйста, поясните с чем это связано и как можно выйти из этой ситуации?
Цитата Сообщение от Uswer Посмотреть сообщение
- вместо конкатенации строк я бы использовал StringBuilder.
Речь идет о сборке сообщения (txt = txt + Chr(d))? В чем будет выгода от использования StringBuilder?
0
2296 / 1612 / 400
Регистрация: 26.06.2017
Сообщений: 4,774
Записей в блоге: 1
04.09.2025, 10:41
Цитата Сообщение от filat18 Посмотреть сообщение
поясните с чем это связано
С вот этими директивами
VB.NET
1
2
#If DEBUG Then
#End If
Цитата Сообщение от filat18 Посмотреть сообщение
Речь идет о сборке сообщения (txt = txt + Chr(d))?
Да.
Цитата Сообщение от filat18 Посмотреть сообщение
В чем будет выгода от использования StringBuilder?
Эффективная работа с памятью.
1
110 / 74 / 6
Регистрация: 08.08.2025
Сообщений: 716
04.09.2025, 13:19
Цитата Сообщение от filat18 Посмотреть сообщение
Thread.SpinWait(10) - никаких проблем опыты пока не показали!
А вот взял другой чип (с той же прошивкой и той же частотой) так его работа стабилизировалась только при Thread.Sleep(1)!?
Встречал, что надо 10 ставить.
Я бы лучше в этот момент отдавал управление Винде, чтобы она свою очередь отработала и вернула управление.
0
Модератор
Эксперт .NET
 Аватар для Yury Komar
4372 / 3442 / 512
Регистрация: 27.01.2014
Сообщений: 6,266
04.09.2025, 19:32
Вызов Thread.Sleep(1) не означает, что поток будет спать ровно одну миллисекунду.
Фактический минимальный интервал, поддерживаемый Windows для Thread.Sleep(), зависит от частоты системного таймера, которая обычно составляет около 16 миллисекунд (один таймерный тик), поэтому, поток будет разбужен с погрешностью около этого значения, а не точно в указанный интервал.
Так, что ставьте 10-15. Меньшее же значение не имеет смысла.
1
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
30.09.2025, 09:09  [ТС]
Прошу пояснить, в примере от Uswer, в Sub ReadData команда currentData.Answer - что именно делает?
сообщает очереди, что эти данные - есть получены!?
0
2296 / 1612 / 400
Регистрация: 26.06.2017
Сообщений: 4,774
Записей в блоге: 1
30.09.2025, 10:49
Если речь идёт об этом куске кода:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        AddHandler broker.DataReceived, AddressOf ReadData
    End Sub
 
    Private Sub ReadData(sender As Object, e As EventArgs)
        If AnswerListBox.InvokeRequired Then
            Me.Invoke(New EventHandler(AddressOf ReadData))
        Else
            Dim currentData As PortBrokerData = Nothing
            While broker.Answers.TryDequeue(currentData)
                AnswerListBox.Items.Add(currentData.Answer)
            End While
        End If
    End Sub
то тут происходит следующее. В обработчике события загрузки формы на событие DataReceived посредника подписывается метод ReadData. Когда в посреднике возникает событие DataReceived вызывается метод ReadData, в котором в потоке формы производится добавление в AnswerListBox всех полученных ответов от устройств опрашиваемых посредником broker.
Цитата Сообщение от filat18 Посмотреть сообщение
команда currentData.Answer - что именно делает?
Это не команда, это свойство "ответ" текущего запроса. Сам текущий запрос вытягивается из очереди Answers посредника.
0
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
16.12.2025, 18:58  [ТС]
Uswer, я очень благодарен за разработку класса ProtokolBroker - удобный и продуктивный, а главное - дающий стабильный результат КОД! Большое спасибо!
и вот движение мысли продолжается: обкатав исходные алгоритмы общения с МК показала, что в отдельных ветках появилась необходимость переключения режима общения... Если исходный режим (вариант №1) был "одна отправка в порт" - "один ответ из порта". То сейчас появилась необходимость выполнить переключение (в рамках имеющегося класса) в другой режим (вариант №2), когда в порт ничего не отправляется, а работает событие чтения всех сообщений из порта - количество сообщений - может быть любое, интервал между сообщениями произвольный. Каждое новое сообщение должно инициировать работу того же саба (Private Sub ReadData) в основном потоке, что и в варианте №1.
Я понимаю, что в классе нужно создать новое свойство, указывающее на вариант работы класса, и нужно создать новый метод, переключающий режим работы, но вот как "мягко" остановить поток ReadWriteProc, без закрытия порта и сброса настроек?
После этого, как я понимаю, нужно инициализировать новый поток ReadWriteProc2, а вот как в нем должен выглядеть замкнутый цикл - пока свойство показывает вариант №2?

Добавлено через 26 минут
Такой код пробую, который не переключает варианты, а переходит с первого на второй.:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#Region "Fields"
 
    ...
    ' поток записи команд
    Private _ReadWriteThread As Thread
 
    ' поток только для чтения входящих данных
    Private _ReadOnlyThread As Thread
 
    ' флаг сигнализирующий о выполнении чтения/записи в порт
    Private IsReadOrWrite As Boolean
 
    ' флаг завершения работы всех потоков
    Private ExitSignal As Boolean = False
 
    ' флаг управления жизнем ReadWriteProc
    Private ReadWriteProcActive As Boolean = True
 
    ' флаг управления жизнем ReadOnlyProc
    Private ReadOnlyProcActive As Boolean = False
    ...
 
#End Region
 
#Region "Metods"
 
    Private Sub Initialize()
        ReadWriteProcActive = True
        _ReadWriteThread = New Thread(AddressOf ReadWriteProc)
        _ReadWriteThread.Start()
    End Sub
 
    ''' <summary>
    ''' Останавливает поток ReadWriteProc. Порт при этом остается открытым.
    ''' </summary>
    Public Sub StopReadWriteProc()
        ReadWriteProcActive = False
        ' Разблокируем ожидание, чтобы поток мог завершиться
        allowReadWrite.Set()
        Try
            If _ReadWriteThread IsNot Nothing AndAlso _ReadWriteThread.IsAlive Then
                _ReadWriteThread.Join(500)
            End If
        Catch
        End Try
    End Sub
 
    ''' <summary>
    ''' Запускает поток, который только читает входящие сообщения и для каждого сообщения вызывает UnloadDataProc/событие.
    ''' </summary>
    Public Sub StartReadOnlyProc()
        If _ReadOnlyThread IsNot Nothing AndAlso _ReadOnlyThread.IsAlive Then
            Return
        End If
        ReadOnlyProcActive = True
        _ReadOnlyThread = New Thread(AddressOf ReadWriteProc2)
        _ReadOnlyThread.IsBackground = True
        _ReadOnlyThread.Start()
    End Sub
 
 
    ''' <summary>
    ''' Второй поток: только чтение входящих сообщений. Для каждого полного сообщения вызывается UnloadDataProc и событие DataReceived.
    ''' </summary>
    Private Sub ReadWriteProc2()
        Dim currentData As String = String.Empty
        Try
            While Not ExitSignal AndAlso ReadOnlyProcActive
                Try
                    ' читаем доступные байты и формируем строку до символа LF (10)
                    If _Port IsNot Nothing AndAlso _Port.IsOpen Then
                        While _Port.BytesToRead > 0
                            Dim d As Integer = _Port.ReadByte()
                            If d = -1 Then
                                Exit While
                            End If
                            If d <> 10 Then
                                currentData &= Chr(d)
                            Else
                                ' конец сообщения
                                Dim msg As String = currentData
                                currentData = String.Empty
                                Answers.Enqueue(New PortBrokerData() With {.Command = String.Empty, .Answer = msg})
 
                                If UnloadDataProc IsNot Nothing Then
                                    syncroContext.Post(UnloadDataProc, New Object)
                                End If
                                RaiseEvent DataReceived(Me, EventArgs.Empty)
                            End If
                        End While
                    End If
                Catch ex As TimeoutException
                    ' ignore read timeout
                Catch ex As Exception
                    ' possible IO exception - break loop on critical issues
                    Console.WriteLine(ex.Message)
                End Try
 
                Thread.Sleep(20) ' не даём 100% CPU в цикле
            End While
        Finally
#If DEBUG Then
            Debug.WriteLine("ReadOnly thread end")
#End If
        End Try
    End Sub
 
#End Region
Пока, вроде работает.. Но если, для кого-то очевидно, что я упускаю какие-то нюансы - пожалуйста, подскажите, пока сильно "не зарылся" в сырой вариант...
0
2296 / 1612 / 400
Регистрация: 26.06.2017
Сообщений: 4,774
Записей в блоге: 1
17.12.2025, 08:22
filat18, посмотрю при случае, пока мало свободного времени.
0
2296 / 1612 / 400
Регистрация: 26.06.2017
Сообщений: 4,774
Записей в блоге: 1
17.12.2025, 21:22
filat18, сделал смену режимов работы брокера, проверяйте. Для смены режима нужно установить свойство BrokerMode, остальное он сам делает.
Вложения
Тип файла: zip ProtokolBroker v3.zip (15.8 Кб, 9 просмотров)
1
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
19.12.2025, 14:25  [ТС]
В v3 cтолкнулся с проблемой возврата к запрос-ответ.
Программа запускается в режиме запрос-ответ - все работает. Переключаю в режим ReadOnly - все работает.
Еще раз переключаю в режиме запрос-ответ - что-то идет не так... По пошаговому проходу показывает, что в:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    Private Sub ReadWriteProc()
        Dim currentCommand As String = String.Empty
        Dim currentData As String
        Dim iteration As Integer ' для демонстрации
        Try
            While Not ExitSignal  ' тут может быть токен отмены
                allowReadWrite.WaitOne() ' ждём разрешения на отправку команды
 
                If ExitSignal Then
                    Exit While
                End If
 
                While (commandQueue.TryDequeue(currentCommand) = True) And (Not ExitSignal)
!тут оказывается, что в поток не дошла команда. currentCommand - остается пустой
!и код сразу перескакивает на стоку:
                allowReadWrite.Reset() ' самоблокируемся до сигнала обработки новой команды
После перезапуска класса SerialPortBroker - все опять работает.

У меня где-то происходит залипание маркера IsReadOrWrite - принудительно присваиваю False в Sub StopWork().
Но в этом случае первая группа запросов ставится в очередь и не отправляется. А когда приходит вторая группа запросов, то происходит отправка всего накопленного.
Сам понимаю, что такой подход - чистое варварство... таким образом получилось добиться прохождения первой группы запросов:
VB.NET
1
2
3
4
5
6
7
8
9
    Private Sub OnBrokerModeChanged()
        Select Case BrokerMode
            Case OperatingMode.Read
                RunOnlyRead()
            Case OperatingMode.ReadWrite
                RunReadWrite()
                RunReadWrite()  ' через повторный запуск
        End Select
    End Sub
0
2296 / 1612 / 400
Регистрация: 26.06.2017
Сообщений: 4,774
Записей в блоге: 1
22.12.2025, 09:24
Цитата Сообщение от filat18 Посмотреть сообщение
У меня где-то происходит залипание маркера IsReadOrWrite
Скорее всего не здесь проблема. Подразумеваю, что проблема в блокировке потока формы на ожидание завершения потока брокера. При этом поток формы не обрабатывает вызовы от брокера. Подумаю как проще решить эту проблему.

Не по теме:

P.S. Вот поэтому и делают протоколы обмена стандартно, а не меняют их логику на ходу.

0
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
22.12.2025, 15:25  [ТС]
Цитата Сообщение от Uswer Посмотреть сообщение
P.S. Вот поэтому и делают протоколы обмена стандартно, а не меняют их логику на ходу.
Понимаю праведность этого постулата, но, к сожалению - работаю, с тем что есть...

Добавлено через 5 минут
P.S. Может, при перезапуске последовательности общения с портом можно принудительно "обнулять" все переменные, до исходного значения?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.12.2025, 15:25

Почему пропадают созданные ячейки таблицы?
Проблемка в удалении данных из контролла (к примеру из таблицы) при обновлении страницы (например по нажатии кнопки). Подскажите как...

Serialport.write и serialport.basestream.write - в чем разница
в чем разница между следующими способами отправки данных на ком-порт?: serPort.BaseStream.Write(data,0,datalen); ...

C# SerialPort Неполный прием сообщений
Добрый день. Долго искал решение своей проблемы, но поиски оказались тщетны. Задача: организовать обмен сообщениями между железом и...

Почему не приходит сообщение группе SignalR?
Методы из хаба. public void UserConnect(string message) { Clients.Group(&quot;managers&quot;).notifyManager(Context.ConnectionId, message);...

Почему в отправляемом почтовом сообщении появляются вопросики?
Все русские символы в отправляемом почтовом сообщении почему-то заменены на вопросики? Может надо указывать кодировку письма? Если да, то...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru