Асинхронный вызов функции

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

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

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

Асинхронный вызов функции

Сообщение insite2012 » 23.11.2013 (Сб) 20:41

Приветствую всех.
Нужен совет, правильно ли я применил асинхронный вызов через делегат.
Суть в следующем. Считываются данные с устройства, через последовательный порт (или пишутся на него), после каждого блока чтения/записи считывается подтверждение. Размер принимаемого блока строго фиксированный. Сначала хотел реализовать все это самым простым способом, без отдельного асинхронного потока, но не удалось, поскольку и сами устройства разные, и работа с ними ведется тоже либо через обычный порт, либо через эмулированный либо вообще через BT-канал. И вдобавок скорость самого компьютера, где запускается программа сильно влияет. И естественно, не удается точно считать определенное количество байт из порта. Вернее, считать-то удается, только приходится приостанавливать поток, и вот время этой остановки очень сильно зависит от тех факторов, что я привел. Поначалу пытался измудриться с разными задержками, а потом решил, что это не выход, надо делать как положено. Вот внизу код. Прошу подсказать, может я что-то пропустил, или можно по иному решить ту же самую задачу.
Код: Выделить всё
'Делегат асинхронного вызова функции чтения
    Private Delegate Function ReadData(ByVal ReaderWD As BinaryReader, ByVal Count As Integer) As Object
'Функция чтения для делегата
    Private Function ReadBytes(ByVal ReaderWF As System.IO.BinaryReader, ByVal Bytes As Integer) As Object
        Dim DataList As New ArrayList
        DataList.AddRange(ReaderWF.ReadBytes(Bytes))
        Return DataList
    End Function
'Создание объектов для чтения и записи
        SPort.Open()
        Dim Reader As New BinaryReader(SPort.BaseStream)
        Dim Writer As New BinaryWriter(SPort.BaseStream)

        'Создание экземпляров асинхронного чтения
        Dim AsyncInvoker As New ReadData(AddressOf ReadBytes)
        Dim AsyncResultA As IAsyncResult
'Запрос данных     
        For V As Integer = 0 To AddressAsc.Length - 1
            CheckSum += AddressAsc(V)
            Writer.Write(AddressAsc, V, 1)
            If V = AddressAsc.Length - 1 Then
                Writer.Write(CType(CheckSum Mod 256, Byte))
            End If
        Next
           
        'Прием данных
        AsyncResultA = AsyncInvoker.BeginInvoke(Reader, 10, Nothing, Nothing)
        TempList.AddRange(AsyncInvoker.EndInvoke(AsyncResultA))
Dulce et decorum est pro patria mori

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

Re: Асинхронный вызов функции

Сообщение FireFenix » 24.11.2013 (Вс) 20:28

insite2012 писал(а):Прошу подсказать, может я что-то пропустил, или можно по иному решить ту же самую задачу.

Суть проблемы если всё рабоатет?

Код: Выделить всё
Writer.Write(CType(CheckSum Mod 256, Byte))

Код: Выделить всё
CType

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

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

Сообщение Qwertiy » 24.11.2013 (Вс) 22:07

insite2012 писал(а):ArrayList

Не надо использовать ArrayList'ы. Они устарели и очень неэффективны.

А ещё, Using'и расставить не помешает.

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 25.11.2013 (Пн) 1:38

Да вроде проблемы как бы и нет (пока, но надеюсь и дальше не будет :D. По крайней мере, что код стал работать стабильнее, хотя и еще далековат от совершенства, но все же... ) Просто в тех книгах, по которым занимался, не советуют использовать несколько потоков без необходимости. Я вот и думаю, была она или нет))
Ув. Qwertiy, а что Вы посоветуете взамен ArrayList-ов? На мой взгляд, очень удобная штука, не приходиться постоянна думать о размерах, один лист по всей процедуре, и для разного количества принимаемых данных. Очищаешь его при необходимости и все. Но если есть что-то другое, более эффективное, посоветуйте, буду благодарен.
PS. Честно говоря, Using еще ни разу не довелось использовать) Наверное, пока не попадался в учебнике. А исключения обрабатываются в самой форме, метод данного класса в форме стоит внутри конструкции Try.... Catch.
Dulce et decorum est pro patria mori

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

Сообщение Qwertiy » 25.11.2013 (Пн) 8:49

List(Of Byte) в твоём случае.

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 25.11.2013 (Пн) 12:00

Qwertiy писал(а):List(Of Byte) в твоём случае.

А не подскажете, где про него прочитать? На MSDN что-то не нашел...
Dulce et decorum est pro patria mori

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

Сообщение Qwertiy » 25.11.2013 (Пн) 12:07

insite2012 писал(а):А не подскажете, где про него прочитать? На MSDN что-то не нашел...

http://msdn.microsoft.com/ru-ru/library/6sh2ey19(v=vs.110).aspx

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 25.11.2013 (Пн) 15:53

Ух ты... А слона-то я и не заметил :D
Еще вопрос. Обязательно ли для приостановки асинхронного потока использовать класс WaitHandle?
Я реализовал это так, как показано ниже. Интересует вопрос, этот объект как раз для этого и служит, чтобы приостановить текущий асинхронный поток до того, как он завершиться, с установленным временем выполнения?
Код: Выделить всё
'Общий цикл чтения
        Do
            'Цикл чтения блока           
            For R As Integer = 0 To MainAsc.Length - 1
                CheckSum += MainAsc(R)
                Writer.Write(MainAsc, R, 1)
                If R = MainAsc.Length - 1 Then
                    Writer.Write(CType(CheckSum Mod 256, Byte))
                End If
            Next

            'Считывание из порта в асинхронном потоке
            'Прием, фильтрация и копирование в основной массив данных
            AsyncResultC = AsyncInvoker.BeginInvoke(Reader, BlockReadSize + 8, Nothing, Nothing)
            Dim TimeOutC As WaitHandle
            TimeOutC = AsyncResultC.AsyncWaitHandle
            TimeOutC.WaitOne(500)
            TempDataList.AddRange(AsyncInvoker.EndInvoke(AsyncResultC))

И второе. Обязательно ли в одной отдельно взятой процедуре/функции создавать несколько объектов IAsyncResult, или можно обойтись одним? У меня сделано так:
Код: Выделить всё
Dim AsyncInvoker As New ReadData(AddressOf ReadBytes)
        Dim AsyncResultA As IAsyncResult
        Dim AsyncResultB As IAsyncResult
        Dim AsyncResultC As IAsyncResult
Dulce et decorum est pro patria mori

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

Сообщение Qwertiy » 25.11.2013 (Пн) 16:23

insite2012 писал(а):CType(CheckSum Mod 256, Byte)

Ну CByte же!

insite2012 писал(а):If R = MainAsc.Length - 1 Then

Зачем оно в цикле?

insite2012 писал(а):Обязательно ли для приостановки асинхронного потока использовать класс WaitHandle?

Не знаю, не разбирался.

insite2012 писал(а):Обязательно ли в одной отдельно взятой процедуре/функции создавать несколько объектов IAsyncResult, или можно обойтись одним?

Это где вообще? Тоже разбираться надо.

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 25.11.2013 (Пн) 21:08

Ув. Qwertiy, по порядку.
Да, CByte, я знаю))) Но в той книге, откуда это вычитал, пробразование типов делалось именно так.
Как Вы видели, в цикле идет передача потока в порт, и одновременно накапливается сумма значений байт передачи. Эта конструкция для того, чтобы после передачи последнего значащего байта в порт пошла контрольная сумма всей посылки (это необходимо).
Про WaitHandle - это вот тут: http://msdn.microsoft.com/ru-ru/library ... e(v=vs.100).aspx
Про IAsyncResult - тоже там же.
Dulce et decorum est pro patria mori

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

Сообщение Qwertiy » 25.11.2013 (Пн) 23:38

insite2012 писал(а):Да, CByte, я знаю))) Но в той книге, откуда это вычитал, пробразование типов делалось именно так.

Ну и что? Знаешь, так делай нормально.

insite2012 писал(а):Эта конструкция для того, чтобы после передачи последнего значащего байта в порт пошла контрольная сумма всей посылки

Так и выкини If, а код поставь вне For'а. Зачем этот if внутри for?

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 26.11.2013 (Вт) 1:19

Сделаю, конечно, просто я же пока учусь, и не все тонкости замечаю. А по КС - так я так сначала и делал, после цикла ее кидал. Но потом мне показалось, что так лучше. Это не так?
Dulce et decorum est pro patria mori

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

Re: Асинхронный вызов функции

Сообщение FireFenix » 26.11.2013 (Вт) 1:35

insite2012 писал(а):Но потом мне показалось, что так лучше. Это не так?

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

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 26.11.2013 (Вт) 8:42

FireFenix писал(а):
insite2012 писал(а):Но потом мне показалось, что так лучше. Это не так?

Что лучше, 1 If + 20 циклов или 20 циклов в которых выполнится 20 if'ов? :)

Думаю первое. :D
Хотя там и If не нужен, КС так или иначе будет высчитана. Просто после 20 циклов ставишь сразу Writer.Write(CByte(CheckSum Mod 256)), и все. :D
Да, а вот что лучше использовать: CByte([data]) или Convert.ToByte([data])? Я читал в учебнике, что второе...
Dulce et decorum est pro patria mori

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

Сообщение Qwertiy » 26.11.2013 (Вт) 12:06

insite2012 писал(а):Думаю первое. :D
Хотя там и If не нужен, КС так или иначе будет высчитана.

Вот именно. Я про это и говорил.

insite2012 писал(а):Да, а вот что лучше использовать: CByte([data]) или Convert.ToByte([data])?

CType. Вот почему.

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 26.11.2013 (Вт) 13:00

Ага... CType... Выходит автор той книги, где я это видел, преобразовывал правильно... Хорошо, большое спасибо.
Dulce et decorum est pro patria mori

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

Сообщение Qwertiy » 26.11.2013 (Вт) 13:17

insite2012 писал(а):Ага... CType... Выходит автор той книги, где я это видел, преобразовывал правильно...

Не совсем так. Под CType я имел в виду не только его, но и все производные типа CByte, CInt, CUint.

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 26.11.2013 (Вт) 13:28

То есть, если я правильно понял, CType([data]) преобразует в том случае, если объект преобразования и может не поддерживать интерфейс IConvertible.
А вот Convert.To... используется, когда про объект преобразования точно известно, что он поддерживает этот интерфейс. В данном случае, компилятор не проверяет тип объекта преобразования, а просто сразу его преобразовывает, в отличие от первого случая. Так?
Dulce et decorum est pro patria mori

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

Сообщение Qwertiy » 27.11.2013 (Ср) 14:38

CType - это приведение типа, если он является родственным или один из типов определяет соответствующий оператор приведения. Если типы известны на этапе компиляции, компилятор сам разворачивает эту конструкцию в необходимое действие. Если же будет передан Object, то он вызовет процедуру конвертирования в рантайме (правда, особую из Microsoft.VisualBasic.CompilerServices.Conversions, а не из System.Convert).
Convert - это динамическое преобразование типов в рантайме, если они реализуют интерфейс IConvertible, плюс, есть перегруженные методы для базовых типов.

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 27.11.2013 (Ср) 19:48

Хорошо, понял.
Кстати, спасибо за подсказку по Using-ам. Если я правильно понял то, что на MSDN сказано, то выходит, если я ее использую вот в такой конструкции:
Код: Выделить всё
Using SPort As New System.IO.Ports.SerialPort
Try
'Тут код, который иcпользует порт
.........
Catch ex As Exeption
MsgBox("Устройство не отвечает",,"Ошибка")
End Try
End Using

то мне не придется даже в исключения вставлять команду на закрытие порта, эта конструкция сама его закроет и освободит все ресурсы, правильно?
Dulce et decorum est pro patria mori

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

Сообщение Qwertiy » 27.11.2013 (Ср) 20:25

insite2012 писал(а):эта конструкция сама его закроет и освободит все ресурсы, правильно?

Да. Но это не мешает ей быть кривой из-за поимки всех исключений и вывода такого сообщения.

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

В Catch ему в любом случае не место. В Finally надо вместо обоих.
Во что Using и разворачивается, кстати.

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 27.11.2013 (Ср) 21:32

Понял, буду пробовать.
Dulce et decorum est pro patria mori

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

Сообщение Qwertiy » 27.11.2013 (Ср) 23:23

А вот я не понял, что ты собрался пробовать ;)

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

Re: Асинхронный вызов функции

Сообщение insite2012 » 27.11.2013 (Ср) 23:39

Qwertiy писал(а):А вот я не понял, что ты собрался пробовать ;)

По Вашему совету, попробую еще Finally. Его пока у меня нет. :D
А еще просветите, если не трудно? Допустим, на компьютере несколько СОМ портов, один "обычный" (в смысле, на материнской плате) и несколько эмулированных (через USB и BT адаптер). В VB есть средства, чтобы этот момент как-то отследить, и отфильтровать определенные порты?
Dulce et decorum est pro patria mori


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

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

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

    TopList  
cron