Delphi
--
Questions
--
Followers
Top Experts
I found some code about Thread (it was a link from this forum), a nice project, but the messagebox in it will not dsiplay. There are no syntax errors. When I debug the source, then the messagebox pops up., but when I run the program normally it doesn't. Also sometimes I get the error of : unknown software exception(...) occured in the application at (....), I click [OK] en then the following error occured: Exception EWin32error in Project1.exe at 00009D9c, code 1400, invalid window handle.
I'm using delphi 5 and Windows 2000 (SP4), the project has two units: it's about a project that's checking if a number is Prime or not. In both cases a message must be displayed. Can somebody help?
{****Begin First unit***************}
unit PrimeForm;
interface
uses
Ā Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Ā StdCtrls;
type
Ā TPrimeFrm = class(TForm)
Ā Ā NumEdit: TEdit;
Ā Ā SpawnButton: TButton;
Ā Ā procedure SpawnButtonClick(Sender: TObject);
Ā private
Ā Ā Ā { Private declarations }
Ā public
Ā Ā Ā { Public declarations }
Ā end;
var
Ā PrimeFrm: TPrimeFrm;
implementation
uses PrimeThread;
{$R *.DFM}
procedure TPrimeFrm.SpawnButtonClick
var
Ā NewThread: TPrimeThrd;
begin
Ā NewThread := TPrimeThrd.Create(True);
Ā NewThread.FreeOnTerminate := True;
Ā try
Ā Ā NewThread.TestNumber := StrToInt(NumEdit.Text);
Ā Ā NewThread.Resume;
Ā except on EConvertError do
Ā Ā begin
Ā Ā Ā NewThread.Free;
Ā Ā Ā ShowMessage('That is not a valid number!');
Ā Ā end;
Ā end;
end;
end.
{****End of First unit**********}
{****Begin Second unit ************}
unit PrimeThread;
interface
uses
Ā Classes;
type
Ā TPrimeThrd = class(TThread)
Ā private
Ā Ā FTestNumber: integer;
Ā protected
Ā Ā function IsPrime: boolean;
Ā Ā procedure Execute; override;
Ā public
Ā Ā property TestNumber: integer write FTestNumber;
Ā end;
implementation
uses SysUtils, Dialogs;
function TPrimeThrd.IsPrime: boolean;
var
Ā iter: integer;
begin
Ā result := true;
Ā if FTestNumber <Ā 0 then
Ā begin
Ā Ā result := false;
Ā Ā exit;
Ā end;
Ā if FTestNumber <= 2 then
Ā Ā exit;
Ā for iter := 2 to FTestNumber - 1 do
Ā begin
Ā Ā if (FTestNumber mod iter) = 0 then
Ā Ā begin
Ā Ā Ā result := false;
Ā Ā Ā {exit;}
Ā Ā end;
Ā end;
end;
procedure TPrimeThrd.Execute;
begin
Ā if IsPrime then
Ā Ā ShowMessage(IntToStr(FTest
Ā else
Ā Ā ShowMessage(IntToStr(FTest
end;
end.
{****End of Second unit**********}
Zero AI Policy
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
You said that your project is about checking if a number is Prime or not. Here is the code (no need for PrimeThread.pas).
//////////////// begin code /////////////////
procedure TMainForm.CheckNumberButto
var
Ā I, J: integer;
begin
Ā if not TryStrToInt(Edit.Text,I) then
Ā begin
Ā Ā MessageDlg('Please enter a valid integer value!',mtWarning,[mbOK],0
Ā Ā Exit;
Ā end;
Ā if I<=0 then
Ā begin
Ā Ā Ā MessageDlg('Please enter a positive integer value!',mtWarning,[mbOK],0
Ā Ā Ā Exit;
Ā end;
Ā if I<=2 then
Ā Ā Exit;
Ā for J:=2 to I-1 do
Ā begin
Ā Ā if (I mod J)=0 then
Ā Ā Ā MessageDlg(IntToStr(I)+' is not a prime number!',mtInformation,[mb
Ā Ā else
Ā Ā Ā MessageDlg(IntToStr(I)+' is a prime number!',mtInformation,[mb
Ā Ā Break;
Ā end;
end;
////////////////// end code ////////////////////
Hope it helps!
Ā :: Cosmin






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
I will start by saying, that the windows system has threads to give processor time segments (time slice) to processes and threads, so to a windows user, it seems like that more than one thread or process is doing something at the same time, however since most computers have only one processor, there can be only one thing being done by the processor at any time. The system will switch the thread using the processor when the time alotment (time slice) for that thread ends or the request for processing from that ends (thread finishes processing or releases its processor time slice). MS says -
A multitasking operating system divides the available processor time among the processes or threads that need it. Windows is designed for preemptive multitasking; it allocates a processor time slice to each thread it executes. The currently executing thread is suspended when its time slice elapses, allowing another thread to run.
The system thread scheduler controls multitasking by determining which of the competing threads receives the next processor time slice. The length of the time slice depends on the operating system and the processor. Because each time slice is small (small for "People" time, approximately 20 milliseconds), to the user multiple threads appear to be executing at the same time.
I will not say anything about thread data syncronozation, except that I have seen several many references that all say the 32-Bit processor can NOT ever access (read, write) a memory block of Less than 32-Bits (4 Bytes), so in my thread usage, for some 32-Bit values I may not use any thread sync at all, to read or write, especially for reading, if incorrect data will not cause an exception. But there are plenty of places that say you must always sync up your thread data access.
Now for the reason that ShowMessage( ) does not work. . To properly keep track of threads and resources assigned to threads, I beleive that there is a system "list of windows created in that thread" maintained for each thread, the windows system has a window message processing (message handling and a message-queue) for each thread, that processes that thread's window messages for only the windows beloning to that thread. The ShowMessage( ) creates a pop-up window (Form) that is owned by the Application window, if you do a Showmessage( ) in a separate thread, there is no GetMessage loop (or other message handling) created for that separate thread by the Forms unit, so the ShowMessage does not work since the Application GetMessage loop is in another thread processing messages from that thread's message-queue.
Since the default message handling methods for forms are all related to the Application window, you probally should create forms ONLY in the main thread, not in any other threads.
You can create windows that work correctly in another thread, but this will require API methods of the system, not methods of the delphi Application window.
For your question, I would not create a window in that thread, even a MessageBox( ) window, since those windows would NOT make the windows of another thread (main thread) Modal. . I would use the API SendMessage( ) function, to get a form in the main thread to use ShowMessage( ) and have a Modal window.
Some code for Form2 - -
const
Ā MsgToThread = WM_USER + 130;
type
Ā TShowMsgThread = class(TThread)
Ā protected
Ā Ā FFormHnd: THandle;
Ā Ā procedure Execute; override;
Ā public
Ā Ā constructor Create(FormHnd: THandle);
Ā end;
Ā TForm2 = class(TForm)
Ā Ā but_ThreadSendMsg: TButton;
Ā Ā procedure but_ThreadSendMsgClick(Sen
Ā private
Ā Ā { Private declarations }
Ā Ā procedure ThreadMsg(var Msg: TMessage); message MsgToThread;
Ā end;
var
Ā Form2: TForm2;
implementation
{$R *.DFM}
constructor TShowMsgThread.Create(Form
begin
FreeOnTerminate := True;
inherited Create(False);
FFormHnd := FormHnd;
end;
procedure TShowMsgThread.Execute;
var
MsgRe: Integer;
begin
// MessageBox( ) shows a window, but does not make main thread windows modal
MessageBox(0,'Thread MessageBox with text display'#10'Does NOT have forms in other threads as Modal',
Ā Ā Ā Ā Ā Ā 'Thread MessageBox', MB_ICONINFORMATION);
// I read a 32-bit Application.Handle with-out thread-sync
// even if this Application.Handle is NON-Correct Data, it does not matter since
// the SetForeGroundWindow( ) will not exception, even with bad data in Application.Handle
SetForeGroundWindow(Applic
if not IsWindow(FFormHnd) then Exit;
Sleep(2000);
// No Form windows are created in this thread
MsgRe := SendMessage(FFormHnd, MsgToThread, 37, 100);
if MsgRe <>Ā 37 then Exit;
Sleep(2000);
SendMessage(FFormHnd, MsgToThread, 37, 54321);
end;
// / / / / / / / / / / / / / / / / / / / / / / / / /
procedure TForm2.ThreadMsg(var Msg: TMessage);
begin
if Msg.WParam = 37 then
Ā begin
Ā Msg.Result := 37;
Ā ShowMessage('This is message 37 from thread '+IntToStr(Msg.LParam)+#10
Ā end else
Ā if Msg.WParam = 73 then
Ā begin
Ā Msg.Result := 73;
Ā ShowMessage('73 - This is message 73 from thread '+IntToStr(Msg.LParam));
Ā end
end;
procedure TForm2.but_ThreadSendMsgCl
begin // button click
TShowMsgThread.Create(Hand
end;
end;
type
Ā TShowWndThread = class(TThread)
Ā private
Ā Ā FMsg1: String;
Ā protected
Ā Ā procedure Execute; override;
Ā public
Ā Ā constructor Create(const Msg: String);
Ā Ā destructor Destroy; override;
Ā end;
// / / / / / / / / / / / / / Ā / / /
implementation
{$R *.DFM}
const
ID_OKBut = 100;
var
aSelf: TShowWndThread;
hThreadWnd: THandle = 0;
function WndProc(hWnd,Msg,wParam,lP
begin
case Msg of
Ā WM_DESTROY: PostQuitMessage(0);
Ā WM_COMMAND: if LOWORD(wParam) = ID_OKBUT then PostMessage(hWnd,WM_CLOSE,
Ā end;
Result := DefWindowProc(hWnd,Msg,wPa
end;
constructor TShowWndThread.Create(cons
begin
FreeOnTerminate := True;
inherited Create(False);
if aSelf <>Ā nil then
Ā Raise Exception.Create('Create Failed - There can only be one instance of TAskThread');
aSelf := Self;
FMsg1 := Msg;
end;
destructor TShowWndThread.Destroy;
begin
aSelf := nil;
inherited Destroy;
end;
procedure TShowWndThread.Execute;
var
wClass: Ā TWndClass;
mainMsg: TMSG;
begin
ZeroMemory(@wClass, SizeOf(wClass));
with wClass do
Ā begin
Ā hInstance := sysInit.hInstance;
Ā hIcon := LoadIcon(0,IDI_QUESTION);
Ā lpfnWndProc := @WndProc;
Ā hbrBackground := COLOR_BTNFACE+1;
Ā lpszClassName := 'TMW Class';
Ā hCursor := LoadCursor(0,IDC_ARROW);
Ā end;
Windows.RegisterClass(wCla
hThreadWnd := CreateWindowEX(0,wClass.lp
Ā Ā Ā Ā Ā WS_SYSMENU or WS_DLGFRAME or WS_CAPTION or WS_VISIBLE,
Ā Ā Ā Ā Ā 140,140,180,110,0,0,hInsta
CreateWindow('BUTTON', 'O K',
Ā Ā WS_VISIBLE or WS_CHILD or BS_PUSHBUTTON or WS_TABSTOP,
Ā Ā 57,50,66,24,hThreadWnd,ID_
SendMessage(CreateWindow('
Ā Ā 1,1,173,46,hThreadWnd,46,h
Ā Ā WM_SETFONT,GetStockObject(
// IMPORTANT
// below is the GetMessage loop for this thread, which does ONLY window message for this thread
// without it the CreateWindow( ) functions abouve are useless
// the ShowMessage( ) procedure does NOT place this in any thread
if hThreadWnd <>Ā 0 then
Ā while GetMessage(mainMsg,0,0,0) do
Ā Ā if not IsDialogMessage(hThreadWnd
Ā Ā Ā begin
Ā Ā Ā TranslateMessage(mainMsg);
Ā Ā Ā DispatchMessage(mainMsg);
Ā Ā Ā end;
end;
// / / / / / / / / / / / / / / / /
procedure TForm2.but_ThreadSendMsgCl
begin // button click
TShowMsgThread.Create(Hand
end;
initialization
finalization
PostMessage(hThreadWnd, WM_DESTROY, 0,0);
end.
Ā = = = = = = = = = = = = = = = = = = = = = = =
maybe this give you alittle more info?
Here is the working code of the second unit (with a memo and the Synchornize function.
unit PrimeThread;
interface
uses
Ā Classes;
type
Ā TPrimeThrd = class(TThread)
Ā private
Ā Ā FTestNumber: integer;
Ā Ā FResultString: string;
Ā protected
Ā Ā function IsPrime: boolean;
Ā Ā Ā procedure UpdateResults;
Ā Ā procedure Execute; override;
Ā public
Ā Ā property TestNumber: integer write FTestNumber;
Ā end;
implementation
uses SysUtils, Dialogs, PrimeForm;
function TPrimeThrd.IsPrime: boolean;
var
Ā iter: integer;
begin
Ā result := true;
Ā if FTestNumber <Ā 0 then
Ā begin
Ā Ā result := false;
Ā Ā exit;
Ā end;
Ā if FTestNumber <= 2 then
Ā Ā exit;
Ā for iter := 2 to FTestNumber - 1 do
Ā begin
Ā Ā if (FTestNumber mod iter) = 0 then
Ā Ā begin
Ā Ā Ā result := false;
Ā Ā Ā {exit;}
Ā Ā end;
Ā end;
end;
procedure TPrimeThrd.UpdateResults;
begin
Ā PrimeFrm.ResultsMemo.Lines
Ā showmessage(FResultString)
end;
procedure TPrimeThrd.Execute;
begin
Ā if IsPrime then
Ā Ā Ā FResultString := IntToStr(FTestNumber) + ' is prime.'
Ā else
Ā Ā FResultString := IntToStr(FTestNumber) + ' is not prime.';
Ā Ā Ā Synchronize(UpdateResults)
Ā {
Ā if IsPrime then
Ā Ā ShowMessage(IntToStr(FTest
Ā else
Ā Ā ShowMessage(IntToStr(FTest
Ā Ā }
end;
end.

Get a FREE t-shirt when you ask your first question.
We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.
Ā Ā Synchronize(UpdateResults)
that adds to the Memo and uses ShowMessage( ), I seemed to get from your comment that you think that the memo addition and ShowMessage are executed in that Thread, This is NOT the case - - they are executed in the main thread, because you call the Ā -
Synchronize( ) method, it is true that you "call" these methods (ShowMessage) in the code for your TThread, but they are "working" (processor time slice) in the main thread, not in your thread's time slice. I even looked at the explanation in the web site you gave for chapter three, and I think he says this about Syncronize, and even has a chart that shows you that the TThread is suspended and the main thread is allowed to run the code in the Syncronize( ) method.
here is the code I have in Classes.pas for the TThread.Synchronize -
procedure TThread.Synchronize(Method
begin
FSynchronizeException := nil;
FMethod := Method;
SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self));
// please notice that this uses the thread-safe and thread-efficient API SendMessage( )
// which runs the code in the FMethod in the main thread, not in this thread
if Assigned(FSynchronizeExcep
end;
I guess I did not understand what you were asking?
The Ā Synchronize( ) Ā TThread method is what you use to run code in the main thread, it has this in the Delphi help, it says -
Ā "Executes a method call within the main VCL thread "Ā but I did not think your question was about that.
I should be also more specific, I apologize for that. Next time I'll be more precisely.
I will guess that you may not get any more posts here, Ā you may should finalize this question. . . .
as to your points question -
since gwalkeriq Ā gave you the link to the Info that you used to develop the code that worked (display the ShowMessage, this a correct way to do that), here at EE it seems the usual is that you might should award him the points. . . ?






EARN REWARDS FOR ASKING, ANSWERING, AND MORE.
Earn free swag for participating on the platform.
You're right about the points, I will give those to gwalkeriq.
Delphi
--
Questions
--
Followers
Top Experts
Delphi is the most powerful Object Pascal IDE and component library for cross-platform Native App Development with flexible Cloud services and broad IoT connectivity. It provides powerful VCL controls for Windows 10 and enables FMX development for Windows, Mac and Mobile. Delphi is your choice for ultrafast Enterprise Strong Developmentā¢. Look for increased memory for large projects, extended multi-monitor support, improved Object Inspector and much more. Delphi is 5x faster for development and deployment across multiple desktop, mobile, cloud and database platforms including 32-bit and 64-bit Windows 10.