Работа с потоками и портом

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Работа с потоками и портом

Сообщение insite2012 » 16.10.2013 (Ср) 13:26

Приветствую.
Вот решил позаниматься с потоками, поскольку многие мои проекты являются очень длинными циклами, и после запуска до окончания работы перестают отвечать. Нашел в книгах несколько способов, даже удалось применить, но хотелось бы узнать поподробнее, чтобы не просто применять описанное в книге, а и понимать, что и как.
Вот часть кода. В закомментированных строках применена функция сама по себе и синхронный вызов потока. И показано применение асинхронного вызова. Сама функция является очень длинным циклом.(Она в отдельном модуле).
Код: Выделить всё
Public Class Form1
    Delegate Function Zapr(ByVal B() As Byte) As Byte()

    Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim Zapros() As Byte = {&HC6, &H4, &H81, &H0, &H21, &H80, &H0}
        Dim Potok As New Zapr(AddressOf Read_Config)
        'Potok(Zapros)
        'Read_Config(Zapros)
        Dim ASync As IAsyncResult
        ASync = Potok.BeginInvoke(Zapros, Nothing, Nothing)
    End Sub

Так вот вопросы следующие: чем отличается синхронный вызов от асинхронного? Само значение этих слов я знаю, но вот хочется знать, что они значат именно в этом контексте. И почему только в случае асинхронного вызова приложение не виснет, а нормально реагирует в процессе выполнения кода. То есть, когда работает цикл, я могу перемещать окно, нажимать другие кнопки и т.п. А в остальных случаях оно встает и так до окончания работы функции.

И еще вопрос, он уже относительно работы с портом.
Вроде более-менее разобрался, применяю вот такую конструкцию:
Код: Выделить всё
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim B0 As Byte() = {&HC6, &H1, &HB0, &HB1}
        Dim A0 As Byte() = {&HC6, &H1, &HB6, &HB7}

        Dim B1 As Byte() = New Byte(7) {}
        Dim A1 As Byte() = New Byte(7) {}

        Try
            SerialPort1.PortName = ComboBox1.Text
            SerialPort1.BaudRate = 9600

            SerialPort1.Open()

            Dim BW As New BinaryWriter(SerialPort1.BaseStream)
            Dim BR As New BinaryReader(SerialPort1.BaseStream)

            For i As Integer = 0 To 3
                BW.Write(B0, i, 1)
            Next

            B1 = BR.ReadBytes(8)

            Thread.Sleep(10)

            For j As Integer = 0 To 3
                BW.Write(A0, j, 1)
            Next

            A1 = BR.ReadBytes(8)

        Catch ex As Exception

        End Try

        TextBox1.Text = ChrW(B1(3)) & ChrW(B1(4)) & ChrW(B1(5)) & ChrW(B1(6)) &
                        ChrW(A1(3)) & ChrW(A1(4)) & ChrW(A1(5)) & ChrW(A1(6))
        SerialPort1.Close()
    End Sub

Как видно из кода, я применил Binary Reader и Binary Writer, хотя можно было бы и просто использовать сам порт. Но мне показалось, что так удобнее, поскольку у данных объектов больше методов.
Подскажите, как будет более правильно. Или может еще какие способы есть.
Dulce et decorum est pro patria mori

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Работа с потоками и портом

Сообщение FireFenix » 16.10.2013 (Ср) 13:37

insite2012 писал(а): и после запуска до окончания работы перестают отвечать.

Если ты про форму, что она виснет, то существует Application.DoEvents

insite2012 писал(а):: чем отличается синхронный вызов от асинхронного? Само значение этих слов я знаю, но вот хочется знать, что они значат именно в этом контексте.

Это же очевидно, что Асинхронная работа, это та, которая выполняется в другом потоке или контексте. А синхронное - всё в одном.

insite2012 писал(а):И почему только в случае асинхронного вызова приложение не виснет, а нормально реагирует в процессе выполнения кода. То есть, когда работает цикл, я могу перемещать окно, нажимать другие кнопки и т.п.

Потому, что твой цикл работает в потоке получения оконных сообщений и форма их не обрабатывает.
А при асинхронной работе - цикл формы и обработка события разделены и работают не зависимо друг от друга
Для обработки оконных сообщений есть Application.DoEvents, как я писал выше

insite2012 писал(а):Как видно из кода, я применил Binary Reader и Binary Writer, хотя можно было бы и просто использовать сам порт. Но мне показалось, что так удобнее, поскольку у данных объектов больше методов.
Подскажите, как будет более правильно. Или может еще какие способы есть.

BinaryReader/Write это потоковая/stream-обёртка. Правильность использования зависит от желаний, и удобства юзера, и архитектуры

Potok
Zapros
и т.д.

Лучше так не называть переменные и не использовать такой транслит, ибо это признак говнокода.
Код: Выделить всё
Thread
Stream

в данном случае лучше
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Работа с потоками и портом

Сообщение insite2012 » 16.10.2013 (Ср) 13:44

Ок, спасибо.
Про Application.DoEvents я читал, и даже пробовал применить вот в таком коде:
Код: Выделить всё
Public Class Form1

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim i As Integer = 0
        Do
            TextBox1.Text = i
            i += 1
            Application.DoEvents()
        Loop
    End Sub

    Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim i As Integer = 0
        Do
            TextBox2.Text = i
            i += 1
            Application.DoEvents()
        Loop
    End Sub
End Class

Но у меня сложилось впечатление, что форма реагирует с небольшим запозданием. Потому решил попробовать с потоками. Ну и как бы надо же и это хоть немного изучить.
Про имена - да, это тестовый проект, в окончательном варианте все будет подредактировано, я читал, что такие названия не приветствуются.и :D
Dulce et decorum est pro patria mori

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 16.10.2013 (Ср) 19:02

insite2012 писал(а):Dim Potok As New Zapr(AddressOf Read_Config)

Он что, наследник потоака? А зачем?

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Работа с потоками и портом

Сообщение insite2012 » 16.10.2013 (Ср) 19:49

Qwertiy писал(а):
insite2012 писал(а):Dim Potok As New Zapr(AddressOf Read_Config)

Он что, наследник потоака? А зачем?

Не знаю. Так в книге было, по которой я учился. :D
Потому и задаю вопросы, не хочется просто тупо копировать, хочется понять суть того, что делаю. Чтобы уметь применить это самому, когда понадобится.
Dulce et decorum est pro patria mori

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Работа с потоками и портом

Сообщение insite2012 » 19.10.2013 (Сб) 0:39

Приветствую всех.
Чтобы не плодить новые темы, решил продолжить эту.
Есть программа (вернее, ее часть, процедура), которая работает с устройством через СОМ порт. Работает вроде корректно, но есть один нюанс.
Пишу и компилирую я ее на нетбуке, и там она работает как надо. Однако стабильность ее работы сильно зависит от быстродействия того компьютера, на котором запускаешь. К примеру, на стационаре (4 ядра по 3,4 ГГц, 8 Гб DDR3 оперативки и т.п.) она просто почти сразу стопорится. Пробовал мониторить обмен по порту, проблема, как я понял, из-за слишком высокой скорости работы, и приходится ставить задержку, в качестве которой применил пустой цикл. Пробовал ставить Thread.Sleep(), но даже при минимальном значении слишком велико становится время работы.
Выходов вижу 2, решил посоветоваться, может кто подскажет самый оптимальный.
1. Разнести потоки передачи в порт и приема из порта и синхронизировать их. На данный момент это для меня пока сложновато. Буду пробовать, конечно, но выйдет не скоро.
2. Придумать функцию задержки и вручную выставлять задержку в зависимости от того компьютера, где будет использоваться программа. Вот и хочется поинтересоваться, никто не встречался с подобными функциями.
вот мой код.
Код: Выделить всё
Public Sub Write_Arcadia(ByVal A() As Byte)
        Dim Zapros() As Byte = {&HA5, &HEE, &H2, &H95, &H4F, &H43, &H90, &H0, Start_1}
        Dim ChSum As Byte = 0
        SP.PortName = Form1.ComboBox1.Text
        SP.BaudRate = 38400
        SP.ReadTimeout = 600
        SP.Open()
        Dim Writer As New System.IO.BinaryWriter(SP.BaseStream)
        Dim Reader As New System.IO.BinaryReader(SP.BaseStream)
        Dim Otvet_Correct As New ArrayList
        Dim Index1 As Integer = 0
        Dim Len As Integer = A.Length
        Dim N As Integer = &H40

        Do
            SP.DiscardInBuffer()
            SP.DiscardOutBuffer()

            Dim TempSum As Integer = 0
            For i As Integer = 0 To Zapros.Length - 1
                TempSum = Convert.ToInt32(TempSum + Zapros(i))
                Writer.Write(Zapros, i, 1)
                Delay(3000000)
            Next

            For j As Integer = 0 To N - 1
                TempSum = Convert.ToInt32(TempSum + A(j + Index1))
                Writer.Write(A, j + Index1, 1)
                Delay(3000000)
            Next

            ChSum = TempSum Mod 256
            Writer.Write(ChSum)

            Otvet_Correct.AddRange(Reader.ReadBytes(11))

            Zapros(7) = Convert.ToInt32((Zapros(7) + &H40) Mod 256)

            If Zapros(7) = &H0 Then
                Zapros(8) = Convert.ToInt32((Zapros(8) + &H1) Mod 256)
            End If

            If Len = 0 Then Exit Do

            Len = Len - &H40
            Index1 = Index1 + &H40

            If Len >= &H40 Then
                N = &H40
            Else
                N = Len
                Zapros(5) = Convert.ToInt32(Len + 3)
                Len = 0
            End If

        Loop       
        SP.Close()
        MessageBox.Show("Запись прошла успешно", "Write", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
    End Sub


И вопрос по работе с портом, созданным из адаптера Bluetooth. С ним вообще непонятно. С нормальным портом (или виртуальным через переходник) работает хорошо, а вот с БТ - вроде работает, но потом вылетает исключение по таймауту. И не знаю, что делать, вроде повышать таймаут нет желания, да и скорость записи выходит черепашья, хотя протокол Bluetooth вроде не такой уж медленный.
Думаю, может есть какие-то другие способы работы с Bluetooth из VB... Может через WinAPI или еще как. Столкнулся с этим первый раз.
Dulce et decorum est pro patria mori

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Работа с потоками и портом

Сообщение FireFenix » 20.10.2013 (Вс) 19:20

insite2012 писал(а):
Код: Выделить всё
        Dim Zapros()
        Dim Otvet_Correct As New ArrayList
        Delay(3000000)


Я бы тоже топорился, не то что программа...

insite2012 писал(а):Выходов вижу 2

3) Разбраться в средствах и написать правильный алгоритм работы!

Есть мнение, что ваш вызов Delay, делает не то, что вы ожидаете
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Работа с потоками и портом

Сообщение insite2012 » 20.10.2013 (Вс) 20:34

Ок. Попробую для начала совсем без него. Я уже кое-что поменял, правда, задержка теперь регулируется от 0 и до сколько хочешь. Сейчас попробую с нулевой, расскажу результат.
Dulce et decorum est pro patria mori

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Работа с потоками и портом

Сообщение insite2012 » 20.10.2013 (Вс) 20:40

Попробовал вообще без задержки. Работает, но скорость все равно намного меньше, чем если с обычным портом. Может это ограничение самого БТ, больше никак не выжать из него?
Dulce et decorum est pro patria mori

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Работа с потоками и портом

Сообщение FireFenix » 21.10.2013 (Пн) 17:39

insite2012 писал(а):Попробовал вообще без задержки.

Я вёл к тому, что твоя задержка работает на много процессорных системах - возможно совсем не так как ты думаешь, что в итоге не совсем правильно работает

insite2012 писал(а):Работает, но скорость все равно намного меньше

ну я же писал
FireFenix писал(а):Разбраться в средствах


у тебя Программа -> COM Port API -> Bluetooth

и ткак ты думаешь, это что-нить значит?
Код: Выделить всё
SP.BaudRate = 38400


И да, Bluetooth - мёртв, хватит некрофилить безжизненное телo! WiFi уже везде есть
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

insite2012
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 109
Зарегистрирован: 22.03.2013 (Пт) 8:06
Откуда: Россия, Саратов

Re: Работа с потоками и портом

Сообщение insite2012 » 22.10.2013 (Вт) 7:58

Ну так это скорость порта) И она там стандартная, то устройство, через которое программа работает, рассчитано именно на такую скорость.
И что касается БТ, опять же, устройства специализированные, и на WiFi пока не рассчитаны...Только БТ...
Dulce et decorum est pro patria mori


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 33

    TopList