type
TPrimeFrm = class(TForm)
{ No change here until public declarations }
public
{ Public declarations }
StringSemaphore: THandle; { Now a semaphore instead of a critical section }
property StringBuf: TStringList read FStringBuf write FStringBuf;
end;
procedure TPrimeFrm.StartBtnClick(Sender: TObject);
begin
if not FStringSectInit then
begin
StringSemaphore := CreateSemaphore(nil, 1, 1, SemName); { Now creating a semaphore instead of a critical section }
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;
CloseHandle(StringSemaphore); { Deleting semaphore }
FStringSectInit := false;
end;
UpdateButtons;
end;
procedure TPrimeFrm.HandleNewData(var Message: TMessage);
begin
if FStringSectInit then {Not necessarily the case!}
begin
WaitForSingleObject(StringSemaphore, INFINITE); { New wait call }
ResultMemo.Lines.Add(FStringBuf.Strings[0]);
FStringBuf.Delete(0);
ReleaseSemaphore(StringSemaphore, 1, nil); { New release call }
{Now trim the Result Memo.}
if ResultMemo.Lines.Count > MaxMemoLines then
ResultMemo.Lines.Delete(0);
end;
end;
procedure TPrimeThrd2.Execute;
var
CurrentNum: integer;
begin
CurrentNum := FStartNum;
while not Terminated do
begin
if IsPrime(CurrentNum) then
begin
WaitForSingleObject(PrimeFrm.StringSemaphore, INFINITE); { New wait call }
PrimeFrm.StringBuf.Add(IntToStr(CurrentNum) + ' is prime.');
ReleaseSemaphore(PrimeFrm.StringSemaphore, 1, nil); { New release call }
PostMessage(PrimeFrm.Handle, WM_DATA_IN_BUF, 0, 0);
end;
Inc(CurrentNum);
end;
end;