From: jcp@werple03.mira.net.au (John Peterson) 
Subject: [delphi] Problems with tips&tricks COMM component 
Date: Sat, 29 Jul 1995 16:24:02 +1000 
 
Firstly, I have only been subscribing to this group for 2 days and  
immediately found help on the major problem I am having in moving from BC++  
-> delphi, namely handling of Data Comms....Thanks for the help. 
 
I've been working with the COMM component and found the following problems  
which could cause lockups on incoming Data. 
 
1. Occasionally we will get a both a CN_RECEIVE and CN_EVENT in one message,  
giving an lParamLo value of 5. TComm.WndProc is written to handle only one  
Event at a time. The following solves this problem: 
 
----------------------------------------------------- 
procedure TComm.WndProc(var Msg:TMessage);       
begin 
  with Msg do 
  begin 
    if Msg=WM_COMMNOTIFY then 
    begin 
      if lParamLo AND CN_EVENT <> 0 then DoEvent; 
      if lParamLo AND CN_RECEIVE <> 0 then DoReceive; 
      if lParamLo AND CN_TRANSMIT <> 0 then DoTransmit; 
    end 
    else 
      Result:=DefWindowProc(FWindowHandle,Msg,wParam,lParam); 
  end; 
end; 
--------------------------------------------------------------- 
 
2. When processing the CN_RECEIVE message, you must read enough characters  
to get below "RxFull" characters left in the receive queue. If this does not  
happen, we will never see another WM_COMMNOTIFY, CN_RECEIVE. 
The way I solve this problem is to check if the queue has less than RxFull  
characters in it, and if not post another WM_COMMNOTIFY message to repeat  
the read. See below... 
 
--------------------------------------------------------------- 
procedure TComm.Read(Data:PChar;Len:Word); 
var 
  Stat : TComStat; 
begin 
  if hComm<0 then exit; 
  if ReadComm(hComm,Data,Len)<0 then Error:=True; 
  GetCommEventMask(hComm,Integer($FFFF)); 
 
  { if we haven't read below FRxFull, reshedule another COMMNOTIFY to read 
        again....this will repeat until we are below 
  } 
  GetCommError(hComm, Stat); 
  if Stat.cbInQue > FRxFull then 
    PostMessage(FWindowHandle, WM_COMMNOTIFY, hComm, CN_RECEIVE); 
end; 
--------------------------------------------------------------- 
 
3. EV_RXCHAR - Is is possible to get into a state where we get an EV_RXCHAR  
event when there is more than 1 character in the queue, this has the effect  
of making the receive queue look like a FIFO. The best way to handle this  
depends on the application. I my apps (comms protocol handlers), the RXCHAR  
handle must be prepared to read more than one character. 
 
Having come from a Borland C++ and OWL background (groan) ;-), Delphi sure  
makes the UI easy, however it appears that there is excessive overhead in  
the decoding the CN_EVENT into a set, then decoding it in the user defined  
handler.  Any comments/experiences on the performance hit Delphi's handlers  
cause, especially in hgigh speed data apps. 
 
regards 
John Peterson 
jcp@werple.mira.net.au 
 
------------------------------------------------------------------------------ 
 
From: pak00465@pixie.co.za (Carl Mes) 
Subject: Problems with COMM component on Tricks & Tips Page ... 
Date: Fri, 28 Jul 1995 10:42:14 +0200 
 
Hello, here's a duplicate of mail I left on Delphi-Talk, regarding the Comm 
component on the Tricks & Tips WWW page. 
 
>> As a thought - have you seen the generic Delphi comm component on the 
> 
>I tried the tComm from the Tips & Tricks page.  I could not get it to  
>work at 14.4 as it seemed to hang when receiving a lot of text.  I added  
>flow control, but that did not fix my problem.  I suggest you send your  
>improvement to the Tip & Tricks site. 
> 
>Andy 
 
The code will hang at high speed, because it is event driven. When the comm 
driver sends an interrupt (See SetCommEventMask in Win/API), it triggers the 
component, which in turn runs the code in your event. The problem is that is 
your event has not finished processing, Delphi will run two events on top of 
each other. You can verify this by putting a ShowMessage('Rhubarb') in the 
event. If you send a couple of characters at the comm port, a couple of 
'Rhubarbs' will pop up on your screen. 
 
The example event code actually processes the incomming characters right 
there and then. This poses a problem: for example : 
- I send 50 characters at the comm-port. 
- After 25 characters the event triggers, with BufferSize as 25. It then 
begins   to read the characters out of the buffer. 
- Characters are still comming in, and after 50 bytes, the event triggers again. 
  The first event however, has only read 10 bytes out of the buffer, so the 
BufferSize will be 40. 
 
Problem! Event1=25 and Event2=40 mean that my code is trying to read 65 
bytes, when there are only 50... Oops! This problem is obviously dependant 
on machine speed, as well as modem speed. If you only use 2400 on a Pentium, 
there is ample time to process incomming characters, and Event1 will finish 
before Event2. 
 
Here's what I did to solve the problem: 
- I created a timer event, which checks for characters every 100ms. 
- In the timer event: 
   - Check if any chars in buffer, return if none. (See functions below) 
   - Disable the timer !!!! (Otherwise the same problem occurs) 
   - Process characters.... 
   - Re-Enable the timer. 
 
The following two functions I added in the comm component, for getting the 
size of the appropriate buffer: 
 
function TComm.GetRxSize:Word; 
var 
  Stat:TComStat; 
begin 
  result := 0; 
  if (hComm < 0) then Exit; 
  GetCommError(hComm, Stat); 
  result := Stat.cbInQue; 
end; 
 
function TComm.GetTxSize:Word; 
var 
  Stat:TComStat; 
begin 
  result := 0; 
  if (hComm < 0) then Exit; 
  GetCommError(hComm, Stat); 
  result := Stat.cbOutQue; 
end; 
 
 
I hope this information is of some use, (Sorry if I was a bit verbose :) 
 
Cheers, CARL (pak00465@pixie.co.za) 
 
 
