Показать сообщение отдельно
  #2  
Старый 07.06.2010, 13:37
Grey_p9 Grey_p9 вне форума
Прохожий
 
Регистрация: 07.06.2010
Адрес: Киров
Сообщения: 2
Репутация: 10
По умолчанию

Чтение должно происходить в не в основном потоке программы, а в специально созданном для этого. Тогда зависания окна программы не будет. Что бы поток не грузил проц на 100% нужно его приостанавливать, а пробуждать по приходу байта в порт. делается примерно так:

Код:
procedure TRdThread.Execute;
Var
  ComStat:TComStat;   //состояние порта
  Errs:Cardinal;
  RdOvr:TOverlapped;  //параметры асинхронной операции чтения

begin
  FillChar(RdOvr,SizeOf(TOverlapped),0);// инициализируем структуру TOverlapped
  RdOvr.hEvent:=CreateEvent(nil,  //параметры защиты, если nil, то беруться от родительского процесса
                            true, //режим управления событием
                            false,//начальное состояние false - несигнальное состояние (занят)
                            nil   //имя обекта nil - нет имени
                            );
  SetCommMask(          //задаем события, которые будут отслеживаться портом
              Port,     //дескриптор порта
              //EV_RXCHAR //маска событий EV_RXCHAR-принят байт
              EV_RXFLAG //маска событий EV_RXCHAR-принят байт
              );

  while not Terminated do begin
    WaitCommEvent(  // инициируем ожидание
                  Port,   //дескриптор порта
                  mask,   //маска событий
                  @RdOvr  //указатель на WrOvr
                );
    WaitForSingleObject(RdOvr.hEvent,INFINITE);  //ждем
    GetOverlappedResult(Port,RdOvr,nRead,false); //после этого в переменной mask будет маска того события которое произошло

    ClearCommError(Port,Errs,@ComStat);       //считываем состояние порта
    nToRead:=ComStat.cbInQue;                 //считываем число байт для чтения из структуры
    GetMem(RcBuf,nToRead);
    if not ReadFile(Port,RcBuf^,nToRead,nRead,@RdOvr) //считываем данные
      then Synchronize(UpdateMainFormlabel5)          //Если данные не считались выводим сообщение об ошибке
      else Synchronize(UpdateMainForm);               //Если данные считались выводим их на форму
    FreeMem(RcBuf);                                   //Освободим буфер
  end;
end;

С помощью CreateEvent сначала создаем объект "событие", потом настраиваем COM порт (функция SetCommMask) так что бы при определенных событиях (например прием байта) изменялось состояние объекта "событие", созданного функцией CreateEvent. Потом "связываем" нужный порт с нужным объектом "событием" с помощью функции WaitCommEvent, затем останавливаем поток(WaitForSingleObject), который проснется автоматически как только изменится сотояние "события", а оно меняется при появлении данных.
Вот как то так.
Ответить с цитированием