Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Basic TThread doesn't work (https://www.delphipraxis.net/107719-basic-tthread-doesnt-work.html)

FaNIX 1. Feb 2008 07:55


Basic TThread doesn't work
 
Ok, I am trying to figure out how this TThread Class work, here is my example:

I am trying to test and see if a thread makes my main application responsive, so that it doesn't seem like it's not responding to events and clicks on the main form, so i created a TThread class, which does a maths calculation, this takes about 8 seconds to complete, giving me time to see if my main app is responsive, but it doesn't seem to work, what I am doing wrong?

My Main Form

Delphi-Quellcode:
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, System.ComponentModel, Borland.Vcl.StdCtrls,Borland.Vcl.ComCtrls, Borland.Vcl.ExtCtrls,
  IdBaseComponent, IdThreadComponent;

type
  TForm3 = class(TForm)
    Button1: TButton;
    MainProgress: TProgressBar;
    IdThreadComponent1: TIdThreadComponent;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);

  private
    { Private declarations }
      procedure MyOnTerminate(Sender:TObject);

  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation

uses MyThread;


{$R *.nfm}
//*******************************************************//
procedure TForm3.Button1Click(Sender: TObject);
var
  TT : TMyThread;
begin

  TT := TMyThread.Create(True);
  TT.FreeOnTerminate := True;

  TT.OnTerminate := MyOnTerminate;
  TT.Resume;

end;
//*******************************************************//
procedure TForm3.MyOnTerminate(Sender: TObject);
begin
  ShowMessage('Done');
end;
//*******************************************************//
end.
My Thread Class:

Delphi-Quellcode:
unit MyThread;

interface

uses Classes,SysUtils,Dialogs,dte_Update_Library_DB,ADODB,ComCtrls;

type
   TMyThread = class(TThread)

  private
     procedure DoIt;

  protected
    procedure Execute; override;

end;

implementation

//*******************************************************//
procedure TMyThread.Execute;
begin
  synchronize(DoIt);
end;
//*******************************************************//
procedure TMyThread.DoIt;
var
  Count : double;
  i  : integer;
begin
  for i := 0 to 900000000000000000 - 1 do
  begin
    Count := Count + i -(i * 2) + i;

  end;

  Terminate;
end;
//*******************************************************//

end.

gsh 1. Feb 2008 08:01

Re: Basic TThread doesn't work
 
You do a synchronize(DoIt); this blocks the application.
Leave the synchronize away and do only synchronize when you whant to access to the MainForm

FaNIX 1. Feb 2008 08:06

Re: Basic TThread doesn't work
 
Zitat:

Zitat von gsh
You do a synchronize(DoIt); this blocks the application.
Leave the synchronize away and do only synchronize when you whant to access to the MainForm

OK, thanks ,got it to work. I don't exacly understand what you mean by only use synchronize when i want access ti the mainform?

Luckie 1. Feb 2008 08:19

Re: Basic TThread doesn't work
 
When you call Synchronize the related code runs in the main forms context. In your case DoIt doesn't run in the context of the thread but in the context of your main form. You shoukd only call Synchronize if you want to access your main form for updating displayed data.

FaNIX 1. Feb 2008 08:26

Re: Basic TThread doesn't work
 
Zitat:

Zitat von Luckie
When you call Synchronize the related code runs in the main forms context. In your case DoIt doesn't run in the context of the thread but in the context of your main form. You shoukd only call Synchronize if you want to access your main form for updating displayed data.

Ahh ok, I see what you meen. But how would I update a label on the main form when calling a method inside the thread with Syncronize? Do i need to include the Mainform unit in my TThread and then access the components from there? Something like form1.label.caption := 'Test'. I'm not sure if that is a nice way of doing it, unless there is another way? :)

Thanks...

Luckie 1. Feb 2008 08:50

Re: Basic TThread doesn't work
 
No, if you want to access controls of your main form you have to use Synchronize because the VCL is not threadsafe. But don't call it everytime in the body of your loop. Call it only evyre 10th time or so.

alzaimar 1. Feb 2008 09:12

Re: Basic TThread doesn't work
 
This is a bit tricky. Here's a simple example:
Delphi-Quellcode:
Type
  TMythread = Class (TThread)
  private
     fLabelMsg : String; // a private field to display in the main form from within a thread
     procedure DoShowMessage;
  Protected
     Procedure Execute; Override;
  End;
Procedure TMyThread.DoShowMessage;
Begin
  MainForm.MyLabel.Caption := fLabelMsg;
End;

Procedure TMyThread.Execute;
Begin
  ....
  fLabelMsg :='Show this!'; // Write what you want to display in your private fields
  Synchronize (DoShowMessage); // Call the method which actually talks to the VCL via Synchronize
  ...
// The Thread terminates automatically, when the Execute-Method is exited.
End;
Bear in mind that ANY access to VCL-Controls (not only on the main form) must be wrapped in a Synchronize call, otherwise your app will hang.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:41 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz