unit PrimeForm2;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, PrimeThread;

const
  WM_DATA_IN_BUF = WM_APP + 1000;
  MaxMemoLines = 20;

type
  TPrimeFrm = class(TForm)
    ResultMemo: TMemo;
    StartBtn: TButton;
    StartNumEdit: TEdit;
    StopBtn: TButton;
    procedure StartBtnClick(Sender: TObject);
    procedure StopBtnClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    FStringSectInit: boolean;
    FPrimeThread: TPrimeThrd2;
    FStringBuf: TStringList;
    procedure UpdateButtons;
    procedure HandleNewData(var Message: TMessage); message WM_DATA_IN_BUF;
  public
    { Public declarations }
    StringSection: TRTLCriticalSection;
    property StringBuf: TStringList read FStringBuf write FStringBuf;
  end;

var
  PrimeFrm: TPrimeFrm;

implementation

{$R *.DFM}

procedure TPrimeFrm.UpdateButtons;
begin
  StopBtn.Enabled := FStringSectInit;
  StartBtn.Enabled := not FStringSectInit;
end;

procedure TPrimeFrm.StartBtnClick(Sender: TObject);
begin
  if not FStringSectInit then
  begin
    InitializeCriticalSection(StringSection);
    FStringBuf := TStringList.Create;
    FStringSectInit := true;
    FPrimeThread := TPrimeThrd2.Create(true);
    SetThreadPriority(FPrimeThread.Handle, THREAD_PRIORITY_BELOW_NORMAL);
    try
      FPrimeThread.StartNum := StrToInt(StartNumEdit.Text);
    except
      on EConvertError do FPrimeThread.StartNum := 2;
    end;
    FPrimeThread.Resume;
  end;
  UpdateButtons;
end;

procedure TPrimeFrm.StopBtnClick(Sender: TObject);
begin
  if FStringSectInit then
  begin
    with FPrimeThread do
    begin
      Terminate;
      WaitFor;
      Free;
    end;
    FPrimeThread := nil;
    FStringBuf.Free;
    FStringBuf := nil;
    DeleteCriticalSection(StringSection);
    FStringSectInit := false;
  end;
  UpdateButtons;
end;

procedure TPrimeFrm.HandleNewData(var Message: TMessage);
begin
  if FStringSectInit then {Not necessarily the case!}
  begin
    EnterCriticalSection(StringSection);
    ResultMemo.Lines.Add(FStringBuf.Strings[0]);
    FStringBuf.Delete(0);
    LeaveCriticalSection(StringSection);
    {Now trim the Result Memo.}
    if ResultMemo.Lines.Count > MaxMemoLines then
      ResultMemo.Lines.Delete(0);
  end;
end;

procedure TPrimeFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  StopBtnClick(Self);
end;

end.