Coder's Guild Mailing List

Delphi: Difficulty With Threads

Posted by Vincent Marcus on 1999-03-11

Whenever I compile I get the error;

[Error] readthread.pas(45): This form of method call only allowed for class
methods

for this line;

     TForm1.ReadPort(nil);

I will change it to;

     ReadPort(nil);

But then I get the error;

[Error] readthread.pas(45): Undeclared identifier: 'ReadPort'

Here is my source.

Thanks,

Vince

unit serialc;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, StdCtrls, ToolWin, ScktComp, Menus, readthread;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Memo2: TMemo;
    StatusBar1: TStatusBar;
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    Help1: TMenuItem;
    ServerSocket1: TServerSocket;
    ClientSocket1: TClientSocket;
    About1: TMenuItem;
    Exit1: TMenuItem;
    TR1: TMenuItem;
    {Begin my functions}
    procedure SetupPort(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure ClosePort(Sender: TObject);
    procedure InitProg(Sender: TObject);
    procedure TR1Click(Sender: TObject);
    procedure ReadPort(Sender: TObject);
    procedure SendPort(var InString: String);
  private
    rt: TReadThread;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  {Begin of my stuff}
  ComFile: THandle;
  ConVal : Integer;

implementation

{$R *.DFM}

procedure TForm1.InitProg(Sender: TObject);
begin
  Memo1.Clear();
  Memo2.Clear();
  ConVal := 1;
  rt := TReadThread.Create (False);
  SetupPort(Nil);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if MessageDlg('Close application ?', mtConfirmation, [mbYes, mbNo], 0) =
mrYes then
    begin
    ClosePort(Nil);
    Action := caFree;
    rt.Free;
    end
  else
    Action := caNone;
end;

procedure TForm1.ClosePort(Sender: TObject);
begin
     CloseHandle(ComFile);
     StatusBar1.Panels[0].Text := 'Serial Port Disconnected ...';
end;

procedure TForm1.SetupPort(Sender: TObject);
const
  RxBufferSize = 256;
  TxBufferSize = 256;
var
  DeviceName : Array[0..80] of Char; {Name of IO Device}
  DCB : TDCB;
  Config : String;
  CommTimeouts : TCommTimeouts;

begin
  StrPCopy(DeviceName, 'COM2:');
  ComFile := CreateFile(DeviceName, GENERIC_READ or GENERIC_WRITE, 0, Nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  Config := 'baud=9600 parity=n data=8 stop=1' + #00;

  if not SetupComm(ComFile, RxBufferSize, TxBufferSize) then
     ShowMessage('SetupComm failed.');

  if not GetCommState(ComFile, DCB) then
     ShowMessage('GetCommState failed.');

  if not BuildCommDCB(@Config[1], DCB) then
     ShowMessage('BuildCommDCB failed.');

  if not SetCommState(ComFile, DCB) then
     ShowMessage('SetCommState failed.');

  with CommTimeouts do
  begin
       ReadIntervalTimeout := 0;
       ReadTotalTimeoutMultiplier := 0;
       ReadTotalTimeoutConstant := 1000;
       WriteTotalTimeoutMultiplier := 0;
       WriteTotalTimeoutConstant := 1000;
  end;

  if not SetCommTimeouts(ComFile, CommTimeouts) then
     ShowMessage('SetCommTimeouts failed.');

  StatusBar1.Panels[0].Text := 'Serial Port Initialized ...';
end;

procedure TForm1.TR1Click(Sender: TObject);
var
   s: String;
begin
     s:='Transmit This!'+#13+#10;
     SendPort(s);
end;

procedure TForm1.ReadPort(Sender: TObject);
var
   s: String;
   d: array[1..80] of Char;
   BytesRead, i: Longword;
begin
   if not ReadFile (ComFile, d, sizeof(d), BytesRead, Nil) then
      ShowMessage('No Transmit!');
   if BytesRead > 0 then
      begin
      s := '';
      for i:=1 to BytesRead do s:=s+d[i];
      Memo1.Lines.Add(s);
      end;
end;

procedure TForm1.SendPort(var InString: String);
var
   BytesWritten: Longword;
begin
   if not WriteFile(ComFile, InString[1], Length(InString), BytesWritten,
Nil) then
      ShowMessage('No Transmit!');
end;
end.

unit readthread;

interface

uses
  Classes;

type
  TReadThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
    procedure ReadLoop;
  end;

implementation

{ Important: Methods and properties of objects in VCL can only be used in a
  method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure TReadThread.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ TReadThread }
uses
    serialc;

procedure TReadThread.Execute;
begin
  { Place thread code here }
  repeat
        Synchronize (ReadLoop);
  until Terminated;
end;

procedure TReadThread.ReadLoop;
begin
     ReadPort(nil);
end;
end.
--------------------
   Vincent Marcus
vmarcus@xx.xxxxx.xxx
  (H) 801-479-2715
  (W) 801-626-7272
  (P) 801-591-2511