title: Using the Events in a serial port component TComPort (v4) from a thread in Delphi?
body: <p>A few years back for one of my applications I moved my serial handling to a thread when a certain app had to respond very quickly to certain serial events.</p>
  
  <p>It was in BDS2006, with an older version (some 3.x?) It was done by having code like this in the tthread.execute:</p>
  
  <pre><code>    while ...
            begin
            events:=[evRxChar];
            { Prepare a stop event for killing a waiting communication wait. }
             try
               comport1.WaitForEvent(events,stopevent.handle,500);
               if evRxChar in events then
                 ComPort1RxChar(comport1,comport1.InputCount); // method of thread.
             on e: exception do {only logs} ;
             end;
  </code></pre>
  
  <p>Initialization was like</p>
  
  <pre><code>procedure TSerThread.initcomport(comportname:string='COM1');
  begin
   comport1:=tcomport.create(nil);
   ComPort1.BaudRate:=br115200;
   ComPort1.DataBits:=dbEight;
   ComPort1.Port:=comportname;
  
   ComPort1.StopBits:=sbOneStopBit;
   ComPort1.Events:=[];
   ComPort1.Connected:=true;
  
   StopEvent := TEvent.Create(nil,{ManualReset}false,{InitialState}false,'StopEvent');
  end;
  </code></pre>
  
  <p>The rxchar method reads using
     comport1.readstr()</p>
  
  <p>I recently had to dig this up, and noticed it didn't work in my Delphi XE, which has tcomport4. Looking in the source I saw remarks that
  comport4 has changed the way it deals with its internal threads ("overlapped" property), but the default seems to be "true" has a comment "classic", and I </p>
  
  <p>assumed that means  compatible with older versions.</p>
  
  <p>Note that the protocols are binary, and all string,char&lt;-> ansistring,ansichar changes have been done like I did in the normal mainthread version</p>
  
  <p>Now the real questions:</p>
  
  <ol>
  <li>does anybody have tcomport4 working in a thread ?</li>
  <li>Are there obvious mistakes in the above?</li>
  <li>or do I need to migrate to a different component?</li>
  </ol>
  
  <p>I'm still debugging what is going on, but am in a hurry, which is while I post this in the hope of quickly getting pointers.</p>
  
  <p><strong>Update</strong></p>
  
  <p>I reinstalled an old turbo delphi copy, and verified it worked there with v3. I fixed a small bug though in the codepath that went a bit different from what I thought (not in the above code)</p>
  
  <p>This allows me to describe the behaviour between dxe/comportv4 and bds2006/comportv3 better; the v4 code generates much more read events (hundreds/second). It seems that the read doesn't delete the read chars from the incoming queue or so.</p>
  
  <p><strong>Update 2</strong></p>
  
  <p>I did a quick test with the newest version, and did the necessary rearranging (kill string function use for an essentially binary protocol). I got stuck for a while because the application crashed on startup, but that is because I use gnugettext, and Comport packages a different (non unicode even?) version. But after that <strong>it works</strong>.</p>
  
  <p>Unfortunately the changes are a bit to risky to propagate back to the production version (completely written protocol decoding), so I'll have to test with inbetween versions (between 4.0 and 4.11f). I'll do that in due time, any suggestion which version was the last readstr(ansistring) one?</p>
  
  <p><strong>Update 3</strong></p>
  
  <p>In the end I simply renamed the 4.11f units and use them in parallel to the old version, using the 4.11f for the threaded codebases and the old one to maintain existing code. </p>
  
  <p>Long term I might simply take the waitforevent code and make an own version. The main problem with it is that it is afaik not possible to see if the wait terminated on timeout, stopevent or whatever. This means you need another timer if you want to e.g. send on regular intervals.</p>