Гость
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Многопоточность в VisualBasic / 16 сообщений из 16, страница 1 из 1
14.09.2016, 14:41
    #39309057
Maksym_t
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Добрый день!

Подскажите как реализовать нижеследующую задумку.

Задача следующая:
Есть сканер штрих-кодов, работающий в режиме эмуляции COM-порта. Необходимо получить из него за один раз, тот объем считанных данных, который был в штрих-коде, а не в буфере приема.

Если просто расположить на форме компонент SerialPort, считывание принятых данных осуществляется через событие DataReceived. Однако вызов этого события происходит не в "Основном", а в дополнительном "Рабочем" потоке. Если писать код используя размещение компонента на форме, то с аккумулированием и передачей данных разом проблем нет. Используя делегат и свойство InvokeRequired класса Control формы в которой объявлен SerialPort, можно очень просто передать данные в "Основной" поток.

Я хочу написать свой класс, допустим BarCodeScanner, который уже будет иметь в себе SerialPort, и событие окончания приема данных, допустим ReceivingEnd.
Вот тут и возникает проблема, каким же образом передать, полученные данные, в "Основной" поток, ведь свойство InvokeRequired класса Control у нас больше нет, и как же обратиться к "Основному" потоку.

Код: vbnet
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.
Public Class MyForm

    Private scanner As New BarCodeScanner()

    Public Sub scanner_ReceivingEnd(ByVal sender as Object, ByVal e As BarCodeScanner.ScannerEventArgs) Handles scanner.ReceivingEnd

        ' Вот тут и возникает проблема, так как данное событие и реакция на него "находится" в "Рабочем" потоке,
        ' а элемент Me.TextBoxBarCode был, создан в "Основном" потоке.
        ' Как же сделать, так чтобы событие ReceivingEnd вызывалось еще не в "Рабочем", а уже в "Основном" потоке? 

        Me.TextBoxBarCode.Text = e.BarCode

    End Sub

End Class

Public Class BarCodeScanner

    Private WithEvents sPort As System.IO.Ports.SerialPort
    Private buffer As String = String.Empty

    Public Event ReceivingEnd(ByVal sender As Object, ByVal e As ScannerEventArgs)

    Public Sub New()

        Me.sPort = New System.IO.Ports.SerialPort(...)
        ...

    End Sub

    Private Sub EndOfReceive()

        RaiseEvent ReceivingEnd(Me, New ScannerEventArgs(buffer))

    End Sub

    Private Sub AttachData(ByVal data As String)

        Me.buffer &= data

    End Sub

    Private Sub sPort_DataReceived() Handles sPort.DataReceived

        Dim str As String = sPort.ReadExisting

        If (str = Chr(26), Me.EndRecived(), Me.AttachData(str))

    End Sub

    ...

End Class

Public Class ScannerEventArgs

    Private barCodeValue As String

    Public Sub New(ByVal barcode As String)

        Me.barCodeValue = barcode

    End Sub

    Public ReadOnly Property BarCode() As String
        Get
            Return barCodeValue
        End Get
    End Property

End Class



Множество примеров просмотрел в интернете, но во всех используется объект Console, и либо рассказывается про использование InvokeRequired.

Как быть подскажите...
...
Рейтинг: 0 / 0
14.09.2016, 16:03
    #39309146
Pallaris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Очевидно, реализовать какое-то событие успешного чтения у BarCodeSanner, на него подписать форму и там чудить чего тебе нужно
...
Рейтинг: 0 / 0
14.09.2016, 16:09
    #39309152
Maksym_t
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Pallarisреализовать какое-то событие успешного чтения у BarCodeSanner
Код: vbnet
1.
2.
3.
Private Sub EndOfReceive()
        RaiseEvent ReceivingEnd(Me, New ScannerEventArgs(buffer))
End Sub


Pallarisна него подписать форму и там чудить чего тебе нужно
Код: vbnet
1.
2.
3.
Public Sub scanner_ReceivingEnd(ByVal sender as Object, ByVal e As BarCodeScanner.ScannerEventArgs) Handles scanner.ReceivingEnd
        Me.TextBoxBarCode.Text = e.BarCode
End Sub


Собственно, в выше указанном примере я это и делаю, и это не будет работать, так как объект Me.TextBoxBarCode создан в "Основном" потоке и получить доступ к нему из "Рабочего" не выходит.
...
Рейтинг: 0 / 0
14.09.2016, 17:11
    #39309196
Pallaris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Будет, если перед обновлением контрола проверять InvokeRequired, и если true, то вызывать control.Invoke и в нем присваивать text
...
Рейтинг: 0 / 0
14.09.2016, 17:29
    #39309211
Maksym_t
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Pallaris,

Может быть, прежде чем отвечать, нужно прочитать первое сообщение?
...
Рейтинг: 0 / 0
14.09.2016, 17:31
    #39309214
Pallaris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Maksym_tВот тут и возникает проблема, каким же образом передать, полученные данные, в "Основной" поток, ведь свойство InvokeRequired класса Control у нас больше нет, и как же обратиться к "Основному" потоку.

Я прочитал про "свойства InvokeRequired больше нет" и этого было достаточно
...
Рейтинг: 0 / 0
14.09.2016, 17:43
    #39309222
Maksym_t
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Pallaris,

Достаточно для чего?
Или то, что Controls, ни разу не принадлежит объекту scanner не очевидно?
Передавать ссылкой Controls? Так тогда нет смысла мне заморачиваться за BarCodeScanner, это не мой путь. Я хочу разобраться с потоками внутри класса BarCodeScanner, без всяких "Вбросов" в него.
...
Рейтинг: 0 / 0
14.09.2016, 17:51
    #39309226
Pallaris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Maksym_t,

достаточно для того, чтобы понять, что ты невнимательно читал про InvokeRequired

Вот первая же ссылка
http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c
...
Рейтинг: 0 / 0
14.09.2016, 18:13
    #39309245
Maksym_t
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Pallaris,

Ок, упущение в первом посте.

Использование класса Control, внутри BarCodeScanner, мягко говоря не уместно.
...
Рейтинг: 0 / 0
14.09.2016, 18:47
    #39309270
Pallaris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Maksym_tPallaris,

Ок, упущение в первом посте.

Использование класса Control, внутри BarCodeScanner, мягко говоря не уместно.

Тебе не нужно его использовать внутри BarCodeScanner. Ты же подписал форму на событие, так и сделай там вот так примерно

Код: c#
1.
2.
3.
4.
5.
6.
if (control.InvokeRequired)
{
     control.Invoke(() =>Me.TextBoxBarCode.Text = e.BarCode);
}
else
     Me.TextBoxBarCode.Text = e.BarCode



Почему ты решил, что из другого потока ты не можешь обратиться вообще к контролу? Поле InvokeRequired как раз и создавалось, чтобы понять, что ты юзаешь контрол в другом потоке.
...
Рейтинг: 0 / 0
14.09.2016, 19:02
    #39309282
Maksym_t
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Pallaris,

Так смысл класса, BarCodeScanner, как раз в том, чтобы не использовать этот велосипед с InvokeRequired, на форме он нужен не спорю, упрощает жизнь. Но я не хочу использовать этот гребаный хук, я как раз и хочу, чтобы событие было не двусмысленно. Если оно возвращает значение, то единственное чтобы в дальнейшем осталось, это всего лишь присвоить это значение туда куда нужно. Облеплять это событие совершенно бесполезным кодом, для того, чтобы потом кто-то сидел и чесал репу "как это работает" это любимый метод работы Майкрософта, я хочу этот идиотизм остановить. По крайней мере в классе BarCodeScanner.

Вот и все, что я хочу сделать =)
...
Рейтинг: 0 / 0
14.09.2016, 19:05
    #39309284
Pallaris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Maksym_t По крайней мере в классе BarCodeScanner.

Мнэээ, у тебя метод scanner_ReceivingEnd(ByVal sender as Object, ByVal e As BarCodeScanner.ScannerEventArgs) в классе MyForm. BarCodeScanner вообще ничего не знает про него и знать не должен. Какие проблемы? Что у тебя не получается? Ты сделал как я написал?
...
Рейтинг: 0 / 0
14.09.2016, 19:45
    #39309294
Maksym_t
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Pallaris,

Да, есть такое, тут просто редактировать уже созданное сообщение нельзя. Я там пару раз ошибся:
1) В процедуре scanner_ReceivingEnd для параметра e не правильный тип, должен быть ScannerEventArgs
2) В процедуре sPort_DataReceived вызов процедуры Me.EndReceived нужно заменить на Me.EndOfReceive

Вставлял из уже написанного класса он просто большой, тут для понимания немного изменил названия.

Проблема в том, что я не хочу использовать класс Control, но так как он каким-то же образом реализован, а это значит, что технически реализовать частично его функциональность можно. А именно обращение к "Основному" потоку, так как New для BarCodScanner выполняется в именно в "Основном" потоке.

То, что ты написал будет работать, но у меня задача не сделать "как придётся, лишь бы работало", а сделать так "как нужно".

Сейчас дома, что-то попробовать смогу только завтра, у меня рабочий день с 11.00 по Москве.
...
Рейтинг: 0 / 0
14.09.2016, 19:47
    #39309298
Maksym_t
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Поправка, не с 11:00, а с 7:00 по Москве.
...
Рейтинг: 0 / 0
14.09.2016, 19:59
    #39309302
Pallaris
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Там, где я писал Control, везде заменить на TextBoxBarCode. Не знаю, на кой я написал слово Control.

Вообще, то, что ты создаешь экземпляр BarScanner в UI-потоке, никакого значения не имеет. Имеет значение, что завершение чтения происходит в другом потоке, и подписанное событие, соответственно, тоже вызывается в нем. Но т.к. визуальные элементы управления в WinForms нельзя менять в потоке, отличном от потока, в котором они были созданы, то изменение нужно обернуть в Invoke/BeginInvoke, чтобы они произошли в UI-потоке.
...
Рейтинг: 0 / 0
14.09.2016, 20:21
    #39309310
Maksym_t
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Многопоточность в VisualBasic
Pallaris,

А какая разница хоть, там будет Me (в данном случае Form) или TextBox, они оба от Control произрастают =)

То есть, ты хочешь сказать, что без InvokeRequired не как не обойтись?

Почему-то мне кажется, Threadings мне все же поможет, просто я ещё не обладаю достаточными знаниями, организацией управлением потоками.
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Многопоточность в VisualBasic / 16 сообщений из 16, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]