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

Вниз

Работа с COM-портом в потоке   Найти похожие ветки 

 
Vitt_lay   (2004-06-22 07:59) [0]

Создал программу для чтения с COM-порта с помощью функций WinAPI.
Работало чтение нормально, но из-за WaitCommEvent программа стопорилась, пока не придут данные.  Так как данные у меня могут прийти в любой момент, решил организовать в отдельном потоке прием информации, но программа стала вылетать с ошибкой "Error reading port" после выполнения ReadFile. Привожу листинг, посоветуйте, пожалуйста, что мне делать. Бьюсь который день, ничего не получается.

procedure TMyThread.Execute;
var
   ComStat: TComStat;
   dwMask, dwError: DWORD;
   OverRead: TOverlapped;
   dwRead: DWORD;
begin
   OverRead.hEvent := CreateEvent(nil, True, False, nil);

   if OverRead.hEvent = Null then
      raise Exception.Create("Error creating read event");

   dwMask := EV_RXCHAR;

  if not SetCommMask(hCom, EV_RXCHAR) then
  raise Exception.Create("Error setting port mask");

  if not WaitCommEvent(hCom, dwMask, @OverRead) then
  begin
    if GetLastError = ERROR_IO_PENDING then
      WaitForSingleObject(OverRead.hEvent, INFINITE)
    else
      raise Exception.Create("Error waiting port event");
  end;

  if not ClearCommError(hCOM, dwError, @ComStat) then
  raise Exception.Create("Error clearing port");

  dwRead := ComStat.cbInQue;

  if dwRead > 0 then
  begin
    if not ReadFile(hCom, Buf, dwRead, dwRead, @OverRead) then
    raise Exception.Create("Error reading port");

  Synchronize(ShowResult);
  end;
end;


 
Digitman ©   (2004-06-22 08:38) [1]

If the function fails, the return value is zero. To get extended error information, call GetLastError.

выполнить это - не судьба ?


 
Vitt_lay   (2004-06-22 09:41) [2]

выполнить это - не судьба ?

Судьба - "параметр задан не верно"
Код 0х57
?
Надеюсь на помощь.


 
Digitman ©   (2004-06-22 09:51) [3]


> Vitt_lay   (22.06.04 09:41) [2]


1.

If hFile was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the read operation starts at the offset specified in the OVERLAPPED structure

не вижу чтобы где-либо в приведенном коде поле смещения в Overlapped-структуре явно устанавливалось тобой

2. как объявлен идентификатор Buf ?


 
Vitt_lay   (2004-06-22 09:58) [4]

1. Не понял я как установить поле смещения... Не поместите ли сюда хотя бы в нескольких словах примерчик?
2. Buf: array[0..$FF] of Byte;

Благодарен Вам за ответы, надеюсь на дальнейшую помощь...


 
Digitman ©   (2004-06-22 10:20) [5]

извиняюсь,

Offset

Specifies a file position at which to start the transfer. The file position is a byte offset from the start of the file. The calling process sets this member before calling the ReadFile or WriteFile function. This member is ignored when reading from or writing to named pipes and communications devices.

т.е. в твоем случае смещение устанавливать необязательно, ибо оно игнорируется ф-цией для коммуник.устройств

а вот после успешного возврата из WaitForSingleObject() перед передачей OVERLAPPED-структуры в ф-цию ReadFile() сбросить ивент в несигналящее состояние не мешало бы (см. ф-цию
ResetEvent)


 
Vitt_lay   (2004-06-22 10:44) [6]

сбросить ивент в несигналящее состояние не мешало бы (см. ф-цию ResetEvent)
поместил перед ReadFile следующее:

 if not ResetEvent(OverRead.hEvent) then
 begin
   ErrTxt :=  SysErrorMessage(GetLastError);
   raise Exception.Create("Error reset event");
 end;

Ошибка чтения порта осталась.


 
Digitman ©   (2004-06-22 10:58) [7]

а CreateFile() перед этим ты точно выполнил с флагом FILE_FLAG_OVERLAPPED ?


 
Vitt_lay   (2004-06-22 11:04) [8]

hCom:=CreateFile(curCom, GENERIC_WRITE or GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

Да :-(


 
jack128 ©   (2004-06-22 11:46) [9]


>    if GetLastError = ERROR_IO_PENDING then
>       WaitForSingleObject(OverRead.hEvent, INFINITE)

ты - оптимист ;-) при таком подходе вполне можно синхронный доступ к порту использовать..

все таки попробуй обнулить всю структуру Overlapped
ZeroMemory(@OverRead, SizeOf(Overlapped));


 
Digitman ©   (2004-06-22 11:51) [10]

а в каком код.потоке ты выполняешь CreateFile() ?
почему это не делается тобой здесь же, в теле Execute() ? Чем это обосновано ?

как ты вообще узнаешь о возникшем исключении ? пошаговой трассировкой в отладчике ? дело в том, что любое исключение, возникающее в контексте доп.трэда ни в коем случае недопустимо "выпускать наружу", это чревато серьезными и непредсказуемыми последствиями для твоего процесса

коль скоро ты ожидаешь возникновение исключений, следует делать хотя бы так

procedure TMyThread.Execute;
begin
try
... // здесь возможны исключения
except
  // здесь любое "непогашенное" исключение "поймано"
  // можно в целях отладки показать его тут же, но ни в коем случае не с пом. Showmessage()
  on e: exception do
   MessageBox(0, PChar(e.classname + " " + e.message), "", mb_ok or mb_setforeground);
end;
end;


 
Digitman ©   (2004-06-22 12:02) [11]


> Vitt_lay   (22.06.04 11:04) [8]


вообще говоря, не думаю что размещение такого несложного алгоритма в доп.треде так уж оправдано


> из-за WaitCommEvent программа стопорилась, пока не придут
> данные


никто не заставляет тебя выполнять именно WaitCommEvent(), можно оставить все это хозяйство в основном код.потоке, но вместо WaitCommEvent() использовать ф-цию MsgWaitForMultipleObjects(), которая кроме ожидания сигнала ивента будет немедленно реагировать на оконные сообщения и события пользовательского ввода/вывода


 
Evgeny V ©   (2004-06-22 12:08) [12]

ReadFile(hCom, Buf, dwRead, dwRead, @OverRead) ->
ReadFile(hCom, Buf[0], dwRead, dwReadДругаЯпеременная, @OverRead) - в дельфи буфер передается как var параметр, далее переменная dwReadДругаЯпеременная - здесь принимается число прочитанных байт, лучше не мешать все в одной переменной, и число байт для чтения и число прочитанных байт, @OverRead - не обязательно использовать операцию чтения в данном случае как оверлаппед, число байт у тебя уже известно и они уже лежат в буфере системы, вряд ли их будет очень много, можно считать и в режиме ожидания. Если все же хочешь использовать именно c OVERLAPPED, то надо так же проверять результат возврата OVERLAPPED операции хотя бы так же как ты это делал для WaitCommEvent


 
Петров Денис ©   (2004-06-22 12:11) [13]

1. Зачем использовать событие со сбросом вручную?
2. Где вызов функции GetOverlappedResult, который должен следовать за WaitForSingleObject?

Кстати, проверка

if not WaitCommEvent(hCom, dwMask, @OverRead) then


при чтении данных из COM-порта при перекрытом вводе-выводе большого смысла не несет - трудно представить ситуацию, когда она вернет TRUE.


 
Digitman ©   (2004-06-22 12:22) [14]


> Evgeny V ©   (22.06.04 12:08) [12]



> Buf[0]


совершенно необязательно

при декларации

Buf: array[0..$FF] of Byte;

компилятор правильно интерпретирует Buf, передав в ф-цию адрес самого первого байта массива


 
Vitt_lay   (2004-06-22 13:51) [15]

Всем большое спасибо за советы и такие быстрые отклики на мое сообщение.
Помогло решить проблему вставка в текст ZeroMemory(@OverRead, SizeOf(Overlapped)) от jack128.
Теперь начну бороться с записью в порт :).

вообще говоря, не думаю что размещение такого несложного алгоритма в доп.треде так уж оправдано

Я думаю отдельно разместить чтение и запись, чтоб не мешать основной обработке принятых данных.


 
Digitman ©   (2004-06-22 16:12) [16]


> Vitt_lay   (22.06.04 13:51) [15]



Помогло решить проблему вставка в текст ZeroMemory()


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


> думаю отдельно разместить чтение и запись, чтоб не мешать
> основной обработке принятых данных.


если таки решил в доп.потоке, то Overlapped-режим можно и не использовать ... пусть это будет бесконечный цикл блокирующего вызова ReadFile или WriteFile - ничего страшного ... условие выхода из цикла - ошибка обращения к несуществующему хэндлу коммуник.канала ... при необходимости прервать цикл хэндл канала просто закрывается вызовом CloseHandle() в контексте любого другого код.потока


 
Vitt_lay   (2004-06-23 07:38) [17]

Спасибо! Благодарен за советы!



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

Форум: "WinAPI";
Текущий архив: 2004.08.01;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.033 c
14-1089582966
ANNIHILATOR
2004-07-12 01:56
2004.08.01
Человек ненавидит то, чего он не понимает...


8-1084713961
iudjen
2004-05-16 17:26
2004.08.01
видеозапись экрана


14-1089962231
Некрофил-затейник__
2004-07-16 11:17
2004.08.01
пути развития и сотрудничество межгалактических рас!


14-1086776471
ИМХО
2004-06-09 14:21
2004.08.01
Чемпионат Европы в Португалии: результаты, впечатления, прогнозы


14-1089872421
Prohodil Mimo
2004-07-15 10:20
2004.08.01
Много ли девушек которые вообще не используют косметики?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский