Delphi/Problem With Thread And Waitfor
Expert: Krisztián Pintér - 3/31/2009
QuestionQUESTION: Hello,
I'm Nikolay Atanasov From Bulgaria. I have an application that use in a background Thread class which communicate with com port with some units. On A for ground Is a user screen with some buttons, controls etc. I use Control for com port communication. I saw the code of this control and there is a threads. I make a small test. This is the code of a test:
unit Unit10;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
Button2: TButton;
procedure Button2Click(Sender: TObject);
private
ImDone: Boolean;
public
{ Public declarations }
end;
TTestThr2 = class(TThread)
private
F: TForm1;
protected
procedure Execute; override;
public
constructor Create(_Form1: TForm1);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TTestThr2 }
constructor TTestThr2.Create(_Form1: TForm1);
begin
F:= _Form1;
inherited Create(False);
Priority:= tpHighest;
// FreeOnTerminate:= True;
Resume;
end;
procedure TTestThr2.Execute;
Var
I: Integer;
begin
repeat
Inc(I);
Sleep(100);
F.Label1.Caption:= InttoStr(I);
until Terminated;
end;
procedure TForm1.Button2Click(Sender: TObject);
Var
T2: TTestThr2;
I,J: Integer;
begin
T2:= TTestThr2.Create(Self);
For I:= 0 to 10000000 Do Begin
For J:= 0 to 10 Do Begin
application.ProcessMessages;
end;
end;
T2.Terminate;
T2.WaitFor;
Showmessage('terminated!');
end;
end.
This Test is working fine. The problem in my application occurs when I call termination method of a thread and after that call waitfor method:
T.Terminate;
T.WaitFor;
The Program is freezing and no way to do anything!
I use Delphi 7.
That is my question.
Best Regards!
ANSWER: hello,
first, your thread design is defective. you MUST NOT update forms from a thread. the good design is that you add some properties to the thread that reports its current progress, and on the main form, use a TTimer to update some controls based on the values of these properties. in addition, you can use some kind of message mechanism to notify the form if there is new information (postmessage does the job).
if you absolutely want to update the main form from the thread (which is not good), at least you must use Synchronize.
about the error you've encountered: i'm unable to reproduce it, the thread stops as expected. are you absolutely sure that the terminate/waitfor is the place where the program hangs? i had to reduce the loop count in your sample code, becasue it runs for several minutes, if not hours, on my PC.
i recommend to wait this way:
for i := 1 to 20 do begin
Application.ProcessMessages;
Sleep(100);
end;
doing so, the waiting time will be 2 seconds.
regs
K
---------- FOLLOW-UP ----------
QUESTION: I agree with your notes and thank you for quick answer. I'll try to correct it. But the main problem is not in design. The main problem is that I have many forms which are created dynamic, shown and release after user set some data. I use showmodal method and this stop the execution of a thread until the form is released. How can I Solve this problem?
Best Regards!
Answerhello,
this is pretty much a different problem than the original. modal forms are designed that way, that is the normal behaviour, and not a problem. showmodal runs an own message loop, and only returns when the form is dismissed. this will not affect message processing or other threads. if you want to show a form and continue working, just call the show method.
as a side note: you CAN NOT show a form from any threads other than the main thread. please note that the VCL is NOT thread safe. aside with a few data classes like TStringList, you simply CAN NOT use these classes from a thread. forms and any controls are included. you CAN NOT create a form from a thread, period. it can be frustrating, but the VCL is just written that way.
i can't really propose anything without knowing your actual goals. but please keep in mind: in delphi, you must use the main thread to show any windows, modal or not. and you can have any number of threads doing background computation or communication tasks. these all must communicate their progress and results to the main thread somehow. many methods exist.
regs,
K