Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];

Вниз

Чтение из Com порта используя поток.   Найти похожие ветки 

 
Kolan ©   (2005-06-01 15:01) [0]

Здравствуйте,
 Делаю класс работы с портом. Всё ясно кроме чтения в отдельном потоке. Просто не понимаю и всё. Вот пример:

Написал два класса - собственно ComPort и для потока.

TComPort = class
 private
   PortHandle: THandle;
   {...}
   FReadThread: TReadComThread;
   {...}
   function StartReadThread: Boolean;
 protected
 public
   {...}
   function ReadByteArray(var Buffer: array of Byte; Length: Cardinal): Boolean;
 published
   {...}

 end;


TReadComThread = class(TThread)
 private
 protected
 public
   procedure Execute(PortHandle: THandle;
     Buffer: array of Byte; Length: Cardinal; TimeOut: Cardinal); override;
 end;


procedure TReadComThread.Execute(PortHandle: THandle;
 Buffer: array of Byte; Length: Cardinal; TimeOut: Cardinal);
var
 ComStat: TComStat;
 dwMask, dwError: DWORD;
 OverRead: TOverlapped;
 dwRead: DWORD;
begin
 OverRead.hEvent := CreateEvent(nil, True, False, nil);
 if OverRead.hEvent = 0 then
 begin
   //AddError(ceReadEvent);
 end;

 FreeOnTerminate := True;
 while not Terminated do
 begin
   if not WaitCommEvent(PortHandle, dwMask, @OverRead) then
   begin
     if GetLastError = ERROR_IO_PENDING then
       WaitForSingleObject(OverRead.hEvent, INFINITE)
     else
     begin
       //AddError(ceWatingPortEvent);
     end;
   end;

   if not ClearCommError(PortHandle, dwError, @ComStat) then
   begin
     //AddError(ceClear);
   end;

   dwRead := ComStat.cbInQue;

   if dwRead > Length then
   begin
     if not ReadFile(PortHandle, Buffer, dwRead, dwRead,@OverRead) then
     begin
       //AddError(ceRead);
     end;
     {Use Тут автор примера предлагает обработать данные}    end;
 end; {while}
end;

В примере, по которому я всё это сделал предлагается обработать всё в потоке как я понял.

А я так не хочу. Я хотел бы в этом отдельном потоке подождать некоторое время. По всей видимости это можно задать тут:
WaitForSingleObject(OverRead.hEvent, INFINITE)
Прочитать из порта. И вернуть прочитанные байты.

Кроме того я непойму вот что: для чтения мне нужен Хендл порта, который описан в другомм классе. Как мне его передать в поток...

Подскажите что я непонимаю? И как сделать правиль то, что я хочу.


 
Digitman ©   (2005-06-01 15:16) [1]

начни стого, что приведенный тобой код даже скомпилирован быть не может - у TThread вирт.метод Execute не имеет параметров, соответственно и в твоем перекрытом методе их быть не должно


> Как мне его передать в поток


например, параметром Create - конструирующего объект метода


 
Kolan ©   (2005-06-01 15:33) [2]


> Digitman ©   (01.06.05 15:16) [1]

Пардон там нет override. Да это я просто чтобы остальные функции проверить написал с параметрами. Чтобы компилироваллнось.


> например, параметром Create - конструирующего объект метода

То есть вы предлагаете сделать поле с хендлом порта и когда я его создаю(поток)из экземпляра TComPort передовать туда Хендел.

Как в таком случае должен работать поток? Мне надо для записи его создовать/удалять каждый раз? Скореевсего будет долго. А если поток всега работает то номер порта может изменится и что тогда?...

Главное как вернуть байты после того как они прочитаны?

Те в классе TComPort я бы хотел сделать функцию Read допустим. Пусть поток всегда запушен и как только что то появилось возврашает результат. Или вот как? Не могу врубится.

Вообшем мне надо чтобы чтение из порта не вешало основной поток.


 
Digitman ©   (2005-06-01 15:58) [3]


> вы предлагаете сделать поле с хендлом порта и когда я его
> создаю(поток)из экземпляра TComPort передовать туда Хендел


именно.
но это только один из вариантов.


> Как в таком случае должен работать поток? Мне надо для записи
> его создовать/удалять каждый раз?


вовсе не обязательно, можно один и тот же поток использовать


> Скореевсего будет долго


в смысле ?


> если поток всега работает то номер порта может изменится
> и что тогда?


и тогда нужно каким-либо образом известитбь поток о смене рабочего хэндла

это не вопрос

реализуй в своем поточном классе метод ReplaceCOMHandle(NewHandle: THandle)


> Вообшем мне надо чтобы чтение из порта не вешало основной
> поток


собственно чтение-то как раз и не "вешает"
"вешает" ожидание данных, если порт открыт и инициализирован для работы с ним в синхр.режиме

а у тебя - асинхронный режим (я вижу что overlapped-механизм тобой таки используется)

так что можно вообще и без доп.потока обойтись

а зачем тебе велосипед изобретать ? есть жа в сети куча всякоразных готовых компонентов для работы с ком-портами , в т.ч. и в асинхр.режиме !
бросил компонент на форму, назначил обработчик OnRead - и всех делов) ... работай себе спокойно в осн.потоке, а как только в ком-порте будут доступны какие-то данные, компонент вызовет твой обработчик, где ты преспокойно прочитаешь эти данные из порта


 
Сибиряк   (2005-06-01 20:14) [4]

На низком уровне из компорта, да и из лпт тоже следует читать в цикле. И ждать сигнала с определенной ноги и анализировать номер ноги. Таже следует предусмотреть вариант выхода из цикла.


 
YurikGL ©   (2005-06-01 21:14) [5]

http://www.kamlit.ru/docs/journals/cd/cd22/off-line/pr/22/article_15.php.htm

Если не ошибаюсь, разобрана работа с COM из потоков

Кстати, я в свое время скачал какой-то компонент и горя не знал :)


 
Германн ©   (2005-06-02 02:12) [6]

Я вот чего не понимаю в упор!

А на кой черт нужна работа с COM-портом в сихронном режиме? При том, что вся логика того же Дельфи сводится к реализации обработчиков событий. А для COM-порта эти события (прерывания) существовали исторически, по крайней мере с конца 80-х прошлого века. Да и сейчас они (эти события) прекрасно реализованы, ну хотя бы в AsyncPro, которая ныне является условно бесплатной, но с исходниками.


 
Defunct ©   (2005-06-02 03:45) [7]

> Германн ©   (02.06.05 02:12) [6]
> А на кой черт нужна работа с COM-портом в сихронном режиме?
И мне тоже интересно.

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

> AsyncPro
С портами ОС должна работать нормально, а не "по-козьи", что вызывает потребность во всяких левых комонентах.


 
Evgeny V ©   (2005-06-02 07:20) [8]


> Defunct ©   (02.06.05 03:45) [7]
> > Германн ©   (02.06.05 02:12) [6]
> > А на кой черт нужна работа с COM-портом в сихронном режиме?
> И мне тоже интересно.
>
> А еще интересно другое, что бесит гораздо сильнее. Почему
> в системе на уровне файловых операций не реализован простой
> механизм, по которому можно было бы проверить "есть данные
> для считывания или нет".


Конкретно для случая COM порта возможность подсмотерть сколько данных в буфере есть, смотри ClearCommError -  COMSTAT - cbInQue. Анологичные операции (функции), хоть и другие по имени и реализации,  подсматривания количества данных в буфере реализованы и для других коммуникационных вещей, которые могут воспользоваться ReadFile, для именованных и неименованных каналовканалов например, сокетов


 
Defunct ©   (2005-06-02 07:42) [9]

> Evgeny V ©   (02.06.05 07:20) [8]
Спасибо!
Очень полезная информация!
Просто диву давался после прочтения статей в инете на эту тему, сплошь и рядом ASyncPro да "замирающий" ReadFile.


 
Digitman ©   (2005-06-02 08:12) [10]


> Defunct ©   (02.06.05 07:42) [9]


> "замирающий" ReadFile


да не "замирает" он вовсе)... если с умом использовать ..
есть же overlapped-режим !
а не нравится overlapped ? еще одна альтернатива есть - ReadFileEx со своими колбэками ..


 
Defunct ©   (2005-06-02 09:51) [11]

> ClearCommError -  COMSTAT - cbInQue.
> есть же overlapped-режим
> ReadFileEx

Если выбирать между этими тремя способами. Первый мне наиболее по душе. Как раз то чего так не хватало.


 
Digitman ©   (2005-06-02 10:03) [12]


> Defunct ©   (02.06.05 09:51) [11]


> Первый мне наиболее по душе. Как раз то чего так не хватало


а я предпочел бы коллбэки в Read/WriteFileEx .. в колбэк-функцию передается достаточная инф-ция и о размере прочитанных/записанных данных и об ошибке, если она имела место быть ...

правда, под Маздаем для СОМ-дивайсов эти ф-ции не м.б. задействованы


 
Германн ©   (2005-06-02 14:00) [13]

2 Defunct ©   (02.06.05 03:45) [7]
>> AsyncPro
>С портами ОС должна работать нормально, а не "по-козьи", что >вызывает потребность во всяких левых комонентах.

Ну это вы, батенька, зря наехали на увы почившую ныне в бозе TurboPower Software. Мы с ней прожили почти всю свою сознательную жизнь.


 
Koan   (2005-06-04 14:09) [14]

Здравствуйте,
 
> именно.
> но это только один из вариантов.

Я понял так и сделал.

> а зачем тебе велосипед изобретать ?

Да компонеты уменя есть. Я хочу из этого dll сделать. Чтобы подключать можно было.

Кстати а это нормальн если у меня компонент на форме, а я сделал класс интерфейса устройства и программы.

И там везде запись выгдлядит:
MainForm.Comm1.WriteByte(B); ...
Это по моему не правильно?

Вот я сделал поле класа потока FData туда кладу байты если они есть
dwRead := ComStat.cbInQue;

   if dwRead > 0 then
   begin
     if not ReadFile(FPortHandle, FData, dwRead, dwRead,@OverRead) then


Как теперь классу ComPort сообщить что считанно с порта и можно забирать.

PS
Причем общение такое: записал пару байт считал пару - тройку.


 
Defunct ©   (2005-06-04 19:55) [15]

> Koan  

CallBack"ом - назначить событие OnRead.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.034 c
14-1117958876
Piter
2005-06-05 12:07
2005.06.29
Что с интернетом?


1-1118054413
Gear
2005-06-06 14:40
2005.06.29
Удаление элемента из динамического массива.


4-1114885483
Okey_
2005-04-30 22:24
2005.06.29
WM_RButtonDown


5-1087822380
RagE
2004-06-21 16:53
2005.06.29
Опять же свой Combobox


1-1118063196
Иван П.
2005-06-06 17:06
2005.06.29
Первое-последнее число текущего месяца в DateTimePicker





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский