Link to home
Start Free TrialLog in
Avatar of omarmf
omarmf

asked on

Control the dinamicly generated, task

Dear Sir

   I am creating multi threaded application, a new form with threade should be created at the run time as on clicking the tree node:

procedure TForm1.CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
Begin
  TForm(Sender).Destroy;
end;

procedure TForm1.TreeView1DblClick(Sender: TObject);
var
  NewForm : TForm;
  thread  : Tthread;
begin
  NewForm := TForm.create(self);
  with NewForm do
  begin
    Left := 250;
    Top := 200;
    Width := 200;
    Height := 300;
    Caption := TreeView1.Selected.Text;
    Name   := 'Form'+TreeView1.Selected.Text;
    OnClose := CustomFormOnClose;
    Show;
  end;
  with Thread do
  begin
    Name   := 'Thread'+TreeView1.Selected.Text;
  end;
end;

I could handle the form events - Like OnClose -
my problem is i dont know how to and where to Control the dinamicly generated, task named 'Thread'+TreeView1.Selected.Text;
I mean Start, stop and the procedure execute

Thank you

Eng: Omar Fayyad
Avatar of shaneholmes
shaneholmes

You first need to create a Decendent from the thread and override its Execute method. It is in that method(Execute) that you place the code you want the thread to perform.


 MyThread = class(TThread)
 protected
  Procedure Execute;override;
 public
 constructor create;
 end;


constructor TMyThread.create;
begin
  inherited create(true);
 //intialize any internal variable here
end;

end;

procedure TMyThread.Execute;
begin
 // your code here
 // if using the VCL, then you need to wrap your code in a Syncronize();
end;



Then spawn your in your main code

 MyThread:= TThread.Create;

Shane
If you want to write initialization code for your new thread class, you must override the Create method. Add a new constructor to the declaration of your thread class and write the initialization code as its implementation. This is where you can assign a default priority for your thread and indicate whether it should be freed automatically when it finishes executing.

MyThread = class(TThread)
 protected
  Procedure Execute;override;
 public
 constructor Create(CreateSuspended: Boolean);
 end;


constructor TMyThread.Create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);
  //Priority := tpIdle; {you can also set the priority)
end;


MyThread:= TMyThread.Create(True); { create suspended }
MyThread.Priority := tpLower;
MyThread.Resume; { now run the thread }


Shane
You should read the Delphi help for TThread very carefully. The following code shows a sample of a statically-created TThread (using File -> New -> Other -> Thread Object).

Please note very carefulkly that ANY access to GUI (VCL) structures requires the use of Synchronize.

code:
--------------------
unit Unit2;

interface

uses
  Classes;

type
  MyThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

implementation

{ Important: Methods and properties of objects in VCL or CLX can only be used
  in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure MyThread.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ MyThread }

procedure MyThread.Execute;
begin
  { Place thread code here }
end;

end.
------------

The Create, Destroy, Execute, Terminate, ... etc. methods are what you will need to use.

There is an example application in the Delphi demos/threads folder that could give you some help.

Also, you might want to pass to your constructor, the TreeNode Item, so you have it when your thread is started.


MyThread = class(TThread)
private
  fNode: TTreeNode;
 protected
  Procedure Execute;override;
 public
 constructor Create(CreateSuspended: Boolean; Node: TTreeNode);reintriduced;
 end;


constructor TMyThread.Create(CreateSuspended: Boolean; Node: TTreeNode);
begin
  inherited create(true);
 //intialize any internal variable here
 fNode:= Node;
end;

end;

procedure TMyThread.Execute;
begin
 Syncronize(DoSomething);
end;


procedure TMyThread.DoSomething
begin
 // do something with FNode
end;
Avatar of omarmf

ASKER

Ok I dont know put the normal thread is not what i want.

I can create New thread

please see my code

//////////////////////////////

unit nismsn;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls, Buttons, RVStyle, RVScroll, RichView,
  ImgList;

type
  TForm1 = class(TForm)
    TreeView1: TTreeView;
    Timer: TTimer;
    senderm: TEdit;
    ListBox1: TListBox;
    Label1: TLabel;
    BitBtn1: TBitBtn;
    Button1: TButton;
    R_ID: TEdit;
    S_ID: TEdit;
    recieverm: TRichView;
    RVStyle1: TRVStyle;
    ImageList1: TImageList;
    FontDialog1: TFontDialog;
    Button2: TButton;
    procedure TimerTimer(Sender: TObject);
    procedure sendermKeyPress(Sender: TObject; var Key: Char);
    procedure FormCreate(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button2Click(Sender: TObject);
    procedure FontDialog1Close(Sender: TObject);
    procedure TreeView1DblClick(Sender: TObject);
    procedure CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  protected
  public
      MsgL: TStringList;
  end;

var
  Form1: TForm1;

implementation

uses thread;

{$R *.dfm}

procedure TForm1.CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
Begin
  TForm(Sender).Destroy;
end;

procedure TForm1.TimerTimer(Sender: TObject);
begin
  // Running all the generated threads //
end;


procedure TForm1.sendermKeyPress(Sender: TObject; var Key: Char);
begin
If Key = #13 Then
 begin
  if(senderm.Text<>'') Then
  MsgL.Add(senderm.Text);
  ListBox1.Items:= MsgL;
  senderm.Text:= '';
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  TreeNodeM1, TreeNodeM2,TreeNodeS: TTreeNode;
begin
  MsgL:= TStringList.Create;
  TreeNodeM1 := TreeView1.Items.Add(nil, 'Online');
  TreeNodeM2 := TreeView1.Items.Add(nil, 'Offline');
  TreeNodeS := TreeView1.Items.AddChild(TreeNodeM2, 'Omar');
  TreeNodeS := TreeView1.Items.AddChild(TreeNodeM1, 'Abdu');
  TreeNodeS := TreeView1.Items.AddChild(TreeNodeM1, 'Modar');
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  if(senderm.Text<>'') Then
    Begin
      MsgL.Add(senderm.Text);
      ListBox1.Items:= MsgL;
      senderm.Text:= '';
    End;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MySQLServer.Connected:= True;
  MySQLReciever.Active:= True;
  Timer.Enabled:= True;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  MySQLServer.Connected:= False;
  MySQLReciever.Active:= False;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  FontDialog1.Execute;
end;

procedure TForm1.FontDialog1Close(Sender: TObject);
begin
  RVStyle1.TextStyles[0].FontName:= FontDialog1.Font.Name;
  RVStyle1.TextStyles[0].Color:= FontDialog1.Font.Color;
  RVStyle1.TextStyles[0].Size:= FontDialog1.Font.Size;
end;

procedure TForm1.TreeView1DblClick(Sender: TObject);
var
  NewForm : TForm;
  RichView: TRichView;
  Thread  : TThread;
begin
  NewForm := TForm.create(self);
  with NewForm do
  begin
    Left := 250;
    Top := 200;
    Width := 200;
    Height := 300;
    Caption := TreeView1.Selected.Text;
    Name   := 'Form'+TreeView1.Selected.Text;
    OnClose := CustomFormOnClose;
    Show;
  end;
  RichView:= TRichView.Create(Self);
  with RichView do
  begin
    Left := 5;
    Top := 5;
    Width := 180;
    Height := 250;
    Name   := 'RichView'+TreeView1.Selected.Text;
    Style  := RVStyle1;
    Add(TreeView1.Selected.Text, 1);
    Format;
    Refresh;
    parent := NewForm;
  end;
  with Thread do
  begin
    Name   := 'Thread'+TreeView1.Selected.Text;
  end;
end;

end.

/////

when i click the node a new form with: ('Form'+TreeView1.Selected.Text) name will be generated then new RichView with ('RichView'+TreeView1.Selected.Text) will be generated what i need is to generate a new thread with: 'Thread'+TreeView1.Selected.Text; name;
then i need to start and stop all the threads in the generated forms from a timer in the main form (Timer), this thred could be writing to the dinamicly generated TreeView; as

this is what i need, creating one thread from delphi i can do.

I will increase the point ... please be Patient and try to help me

Eng. Omar Fayyad
What is it that you would like each thread to do? That code will reside in the TThread.Execute procedure or (if you use the code listed above by shaneholmes, which is good code except for a misspelling of "reintroduced"), in the TMyThread.DoSomething procedure.

You will have to add a private variable  - fName to your thread class, so you will have some kind of ID.

constructor TMyThread.Create(CreateSuspended: Boolean; Node: TTreeNode);
begin
  inherited create(true);
  fNode:= Node;
  fName:= 'Thread ' + Node.Text;
end;


 You will most likely also have to keep a TThread list (You could use a TList, a TObjectList, etc) to keep track of your threads.

  I would recommend using a TObjectList, that way, they are destroyed (set TObjectLists   OwnsObjects = True) when your   main form is destroyed.

 This will also allow you to iterate through and find the Thread you are looking for ny the fName variable described


UNLESS of course you will be tracking it by ThreadId property.

If you want to email me your code (Im using Delphi 7) and you dont use anything special for components, I will take a look


Shane  (homesshane AT charter DOT net)
 
Avatar of omarmf

ASKER

Ok the last answer seems to be the nearest solution

constructor TMyThread.Create(CreateSuspended: Boolean; Node: TTreeNode);
begin
  inherited create(true);
  fNode:= Node;
  fName:= 'Thread ' + Node.Text;
end;

i beleave that the second parometer should be the task name, it is giving error, unknown fName, fNode .... i tryied to declarify fNode as TTreeNode, it is ok put what about fName and how it will pass the thread name ???

one more thing is the execute prucedure for the tasks generated ????
Dont know what to do ....
Omar Fayyad
Did you et my email? WIth the code

SHane
If you don't know what to do in the thread, why are you creating one in the first place? Threads are only useful if the executed code would otherwise block further processing if done in a single thread.

If the only reason is to allow editing and manipulation of the created forms, then a thread is useless because you'd have to "Synchronize" back to the main therad anyway for GUI access.
Reading back, I see references to a SQL server. Is the intention that each thread communicates as a sort of "middleware" to a client attached over some communication channel and then passes SQL queries back and forth?

If so then the thread Execute procedure should just be a repeating transaction handler, querying the end user for input, possibly parsing it and creating an SQL query, passing the query to the SQL server (perhaps under control of a mutex - a mutual exclusion sempahore), sending the results back to the user over the communications channel and possibly indicating status information on the created form(s) via a Synchronize procedure. The Execute procedure should also wath for termination requests.

If this is what you're trying to accomplish, there are proably better ways using some of the built-in Delphi database support.
Avatar of omarmf

ASKER

Yes mr Shane

I got it. and it has what i need.

  I will try to finish what i need and check it again then i will close the
Let me know if you need anymore help
Avatar of omarmf

ASKER

Dear Mr.sftweng

  you got the point, each of these forms is connected to the DB put with diffirent parometers. i cant accept all of them in one form because they are for supportin diffirent emloeeys.  each connection in the form is quiring a special records, the records are in a remote area so it will take more then 3 sec to be completed this will blok the form.

i tryed to recive all the records then disriputing them to form. it is unpossible. thats whay i had to crete task for each.   the task are 6 maximum so i think it will work will   Mr. Shane did a grate thing for me the part of creating task with the same name as the node.

i will be trying now with prossing each creted connection with the different tasks from the task list.  i need some time to try this and i will use the experts for help.

thank you for your recomindations we can gain a lot from the experts

it is med night now, i wil continu tomorro.

thanks again

regard
Omar Fayyad
I am posting the unit I had Omar email me so i could look. I have made a few changes to his code for creating a Thread based on his needs.

Shane

unit nismsn;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls, Buttons, ImgList, Contnrs;

type

  TXThread = class(TThread)
  private
    { Private declarations }
   fNode: TTreeNode;
   fName: String;
  protected
    procedure Execute; override;
  public
   property Name: String read fName write fName;
   property Node: TTreeNode read fNode write fNode;
   constructor Create(CreateSuspended: Boolean; Node: TTreeNode);
 end;

  TForm1 = class(TForm)
    TreeView1: TTreeView;
    Timer: TTimer;
    senderm: TEdit;
    ListBox1: TListBox;
    Label1: TLabel;
    BitBtn1: TBitBtn;
    Button1: TButton;
    R_ID: TEdit;
    S_ID: TEdit;
    ImageList1: TImageList;
    FontDialog1: TFontDialog;
    recieverm: TRichEdit;
    procedure sendermKeyPress(Sender: TObject; var Key: Char);
    procedure FormCreate(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure TreeView1DblClick(Sender: TObject);
    procedure CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
      MsgL: TStringList;
      ThreadList: TObjectList;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TXThread.Execute;
begin
 // your code here
 // if using the VCL, then you need to wrap your code in a Syncronize();
end;

constructor TXThread.Create(CreateSuspended: Boolean; Node: TTreeNode);
begin
 inherited Create(CreateSuspended);
 fNode:= Node;
end;

procedure TForm1.CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
Begin
  TForm(Sender).Destroy;
end;

procedure TForm1.sendermKeyPress(Sender: TObject; var Key: Char);
begin
If Key = #13 Then
 begin
  if(senderm.Text<>'') Then
  MsgL.Add(senderm.Text);
  ListBox1.Items:= MsgL;
  senderm.Text:= '';
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  TreeNodeM1, TreeNodeM2: TTreeNode;
begin
  MsgL:= TStringList.Create;
  ThreadList:= TObjectList.Create;
  ThreadList.OwnsObjects:= True;
  TreeNodeM1 := TreeView1.Items.Add(nil, 'Online');
  TreeNodeM2 := TreeView1.Items.Add(nil, 'Offline');
  TreeView1.Items.AddChild(TreeNodeM2, 'Omar');
  TreeView1.Items.AddChild(TreeNodeM1, 'Abdu');
  TreeView1.Items.AddChild(TreeNodeM1, 'Modar');
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  if(senderm.Text<>'') Then
    Begin
      MsgL.Add(senderm.Text);
      ListBox1.Items:= MsgL;
      senderm.Text:= '';
    End;
end;

procedure TForm1.TreeView1DblClick(Sender: TObject);
var
  NewForm : TForm;
  RichEdit: TRichEdit;
  AThread  : TXThread;
begin
  NewForm := TForm.create(self);
  with NewForm do
  begin
    Left := 250;
    Top := 200;
    Width := 200;
    Height := 300;
    Caption := TreeView1.Selected.Text;
    Name   := 'Form'+TreeView1.Selected.Text;
    OnClose := CustomFormOnClose;
    Show;
  end;
  RichEdit:= TRichEdit.Create(Self);
  with RichEdit do
  begin
    Left := 5;
    Top := 5;
    Width := 180;
    Height := 250;
    Name   := 'RichEdit'+TreeView1.Selected.Text;
    parent := NewForm;
  end;
  AThread:= TXThread.Create(True, TreeView1.Selected);
  AThread.Name:= 'Thread'+ AThread.Node.Text;
  ThreadList.Add(AThread);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 ThreadList.Free;
end;

end.
Oops, I posted th wrong unit, here is the correct one.


 TXThread = class(TThread)
  private
    { Private declarations }
   fNode: TTreeNode;
   fName: String;
  protected
    procedure Execute; override;
  public
   property Name: String read fName write fName;
   property Node: TTreeNode read fNode write fNode;
   constructor Create(Node: TTreeNode);reintroduce;
 end;

  TForm1 = class(TForm)
    TreeView1: TTreeView;
    Timer: TTimer;
    senderm: TEdit;
    ListBox1: TListBox;
    Label1: TLabel;
    BitBtn1: TBitBtn;
    Button1: TButton;
    R_ID: TEdit;
    S_ID: TEdit;
    ImageList1: TImageList;
    FontDialog1: TFontDialog;
    recieverm: TRichEdit;
    procedure sendermKeyPress(Sender: TObject; var Key: Char);
    procedure FormCreate(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure TreeView1DblClick(Sender: TObject);
    procedure CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
      MsgL: TStringList;
      ThreadList: TObjectList;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TXThread.Execute;
begin
 ShowMessage(Self.Name);
end;

constructor TXThread.Create(Node: TTreeNode);
begin
inherited Create(False);
 fNode:= Node;
end;

procedure TForm1.CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
Begin
  TForm(Sender).Destroy;
end;

procedure TForm1.sendermKeyPress(Sender: TObject; var Key: Char);
begin
If Key = #13 Then
 begin
  if(senderm.Text<>'') Then
  MsgL.Add(senderm.Text);
  ListBox1.Items:= MsgL;
  senderm.Text:= '';
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  TreeNodeM1, TreeNodeM2: TTreeNode;
begin
  MsgL:= TStringList.Create;
  ThreadList:= TObjectList.Create;
  ThreadList.OwnsObjects:= True;
  TreeNodeM1 := TreeView1.Items.Add(nil, 'Online');
  TreeNodeM2 := TreeView1.Items.Add(nil, 'Offline');
  TreeView1.Items.AddChild(TreeNodeM2, 'Omar');
  TreeView1.Items.AddChild(TreeNodeM1, 'Abdu');
  TreeView1.Items.AddChild(TreeNodeM1, 'Modar');
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  if(senderm.Text<>'') Then
    Begin
      MsgL.Add(senderm.Text);
      ListBox1.Items:= MsgL;
      senderm.Text:= '';
    End;
end;

procedure TForm1.TreeView1DblClick(Sender: TObject);
var
  NewForm : TForm;
  RichEdit: TRichEdit;
  AThread  : TXThread;
begin
  NewForm := TForm.create(self);
  with NewForm do
  begin
    Left := 250;
    Top := 200;
    Width := 200;
    Height := 300;
    Caption := TreeView1.Selected.Text;
    Name   := 'Form'+TreeView1.Selected.Text;
    OnClose := CustomFormOnClose;
    Show;
  end;
  RichEdit:= TRichEdit.Create(Self);
  with RichEdit do
  begin
    Left := 5;
    Top := 5;
    Width := 180;
    Height := 250;
    Name   := 'RichEdit'+TreeView1.Selected.Text;
    parent := NewForm;
  end;
  AThread:= TXThread.Create(TreeView1.Selected);
  AThread.Name:= 'Thread'+ AThread.Node.Text;
  ThreadList.Add(AThread);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 ThreadList.Free;
end;

end.
Avatar of omarmf

ASKER

Again I fail

The thing i need now is to make the label in each generated form run a counter from 1 to 10000 in the new created thread On Clicking the button in the same generated form.

I trayed to get the generated components names in the new generated form put i could only have the name of the event component ( Button in My case )
and the parent (The form name)

Please Try to Help me.


unit nismsn;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls, Buttons, ImgList, Contnrs;

type

TXThread = class(TThread)
  private
    { Private declarations }
   fNode: TTreeNode;
   fName: String;
  protected
    procedure Execute; override;
  public
   property Name: String read fName write fName;
   property Node: TTreeNode read fNode write fNode;
   constructor Create(Node: TTreeNode);reintroduce;
 end;

  TForm1 = class(TForm)
    TreeView1: TTreeView;
    recieverm: TRichEdit;
    procedure FormCreate(Sender: TObject);
    procedure TreeView1DblClick(Sender: TObject);
    procedure CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BtnClickEv(Sender: TObject);
  private
    { Private declarations }
  public
      MsgL: TStringList;
      ThreadList: TObjectList;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BtnClickEv(Sender: TObject);
begin
  ShowMessage(IntToStr(TForm(TBitBtn(Sender).Parent.Name).ComponentCount));
  ShowMessage(TBitBtn(Sender).Name);
  ShowMessage(TBitBtn(Sender).Parent.Name);
  //ShowMessage(TForm(TBitBtn(Sender).Parent.Name).Components[4].Name);
end;

procedure TXThread.Execute;
begin
  form1.recieverm.Lines.Add('Thread: '+self.Name+' Is Running');
end;

constructor TXThread.Create(Node: TTreeNode);
begin
inherited Create(False);
 fNode:= Node;
end;

procedure TForm1.CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
Begin
  TForm(Sender).Destroy;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  TreeNodeM1, TreeNodeM2: TTreeNode;
begin
  MsgL:= TStringList.Create;
  ThreadList:= TObjectList.Create;
  ThreadList.OwnsObjects:= True;
  TreeNodeM1 := TreeView1.Items.Add(nil, 'Online');
  TreeNodeM2 := TreeView1.Items.Add(nil, 'Offline');
  TreeView1.Items.AddChild(TreeNodeM2, 'Omar');
  TreeView1.Items.AddChild(TreeNodeM1, 'Abdu');
  TreeView1.Items.AddChild(TreeNodeM1, 'Modar');
end;

procedure TForm1.TreeView1DblClick(Sender: TObject);
var
  NewForm : TForm;
  RichEdit: TRichEdit;
    Edit  : TEdit;
    BitBtn: TBitBtn;
  NewLabel: TLabel;
  AThread : TXThread;
begin
  NewForm := TForm.create(self);
  with NewForm do
  begin
    Left := 100;
    Top := 200;
    Width := 250;
    Height := 350;
    Caption := TreeView1.Selected.Text;
    Name   := 'Form'+TreeView1.Selected.Text;
    OnClose := CustomFormOnClose;
    Show;
  end;
  RichEdit:= TRichEdit.Create(Self);
  with RichEdit do
  begin
    Left := 5;
    Top := 5;
    Width := 180;
    Height := NewForm.Height - 60;
    text:= '';
    Name   := 'RichEdit'+TreeView1.Selected.Text;
    parent := NewForm;
  end;
  Edit:= TEdit.Create(Self);
  with Edit do
  begin
    Left := RichEdit.Left;
    Width := RichEdit.Width;
    Height := 300;
    Top := RichEdit.Height+10;
    Name   := 'Edit'+TreeView1.Selected.Text;
    text := '';
    parent := NewForm;
  end;
  BitBtn:= TBitBtn.Create(Self);
  with BitBtn do
  begin
    Left := edit.width + 10;
    Width := 50;
    Height := Edit.Height;
    Top := Edit.Top;
    Name   := 'BitBtn'+TreeView1.Selected.Text;
    Caption:= 'Send';
    OnClick:= BtnClickEv;
    parent := NewForm;
  end;
  NewLabel:= TLabel.Create(Self);
  with NewLabel do
  begin
    Left := edit.width + 30;
    Width := 50;
    Height := Edit.Height;
    Top := 30;
    Name   := 'Caption'+TreeView1.Selected.Text;
    Caption:= '0';
    parent := NewForm;
  end;
  AThread:= TXThread.Create(TreeView1.Selected);
  AThread.Name:= 'Thread'+ AThread.Node.Text;
  ThreadList.Add(AThread);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 ThreadList.Free;
end;

end.


Thank You

Omar Fayyad

In TXThread.Execute you are using form1 directly. I have tried to emphasize it but I'll say it again - you MUST use Synchronize.
Omarmf,

I have made the changes below. I am emailing you the code as well.

Shane


unit nismsn;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls, Buttons, ImgList, Contnrs;

type

  TXThread = class(TThread)
  private
    { Private declarations }
   fNode: TTreeNode;
   fName: String;
   fForm: TForm;
   fLabel: TLabel;
   fButton: TButton;
  protected
    procedure DoCount;
    procedure Execute; override;
  public
   property Name: String read fName write fName;
   property ThreadNode: TTreeNode read fNode write fNode;
   property ThreadForm: TForm read fFOrm write fForm;
   property FormLabel: TLabel read fLabel write fLabel;
   property FormButton: TButton read fButton write fButton;
   constructor Create(ANode: TTreeNode; AForm: TForm; ALabel:
                      TLabel; AButton: TButton);reintroduce;
 end;

  TForm1 = class(TForm)
    TreeView1: TTreeView;
    Timer: TTimer;
    senderm: TEdit;
    ListBox1: TListBox;
    Label1: TLabel;
    BitBtn1: TBitBtn;
    Button1: TButton;
    R_ID: TEdit;
    S_ID: TEdit;
    ImageList1: TImageList;
    FontDialog1: TFontDialog;
    recieverm: TRichEdit;
    procedure sendermKeyPress(Sender: TObject; var Key: Char);
    procedure FormCreate(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure TreeView1DblClick(Sender: TObject);
    procedure CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BtnClickEv(Sender: TObject);
  private
    { Private declarations }
  public
      MsgL: TStringList;
      ThreadList: TObjectList;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TXThread.DoCount;
var
 I: Integer;
begin
 for I:= 0 to 10000 do
 FormLabel.Caption:= inttostr(I);
end;

procedure TXThread.Execute;
begin
 Synchronize(DoCount);
end;

constructor TXThread.Create(ANode: TTreeNode; AForm: TForm;
                            ALabel: TLabel; AButton: TButton);
begin
inherited Create(False);
 fNode:= ANode;
 fForm:= AForm;
 fLabel:= ALabel;
 fButton:= AButton;
end;

procedure TForm1.CustomFormOnClose(Sender: TObject; var Action: TCloseAction);
Begin
  TForm(Sender).Destroy;
end;

procedure TForm1.sendermKeyPress(Sender: TObject; var Key: Char);
begin
If Key = #13 Then
 begin
  if(senderm.Text<>'') Then
  MsgL.Add(senderm.Text);
  ListBox1.Items:= MsgL;
  senderm.Text:= '';
 end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  TreeNodeM1, TreeNodeM2: TTreeNode;
begin
  MsgL:= TStringList.Create;
  ThreadList:= TObjectList.Create;
  ThreadList.OwnsObjects:= True;
  TreeNodeM1 := TreeView1.Items.Add(nil, 'Online');
  TreeNodeM2 := TreeView1.Items.Add(nil, 'Offline');
  TreeView1.Items.AddChild(TreeNodeM2, 'Omar');
  TreeView1.Items.AddChild(TreeNodeM1, 'Abdu');
  TreeView1.Items.AddChild(TreeNodeM1, 'Modar');
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  if(senderm.Text<>'') Then
    Begin
      MsgL.Add(senderm.Text);
      ListBox1.Items:= MsgL;
      senderm.Text:= '';
    End;
end;

procedure TForm1.BtnClickEv(Sender: TObject);
begin
  ShowMessage(IntToStr(TForm(TBitBtn(Sender).Parent.Name).ComponentCount));
  ShowMessage(TBitBtn(Sender).Name);
  ShowMessage(TBitBtn(Sender).Parent.Name);
  //ShowMessage(TForm(TBitBtn(Sender).Parent.Name).Components[4].Name);
end;

procedure TForm1.TreeView1DblClick(Sender: TObject);
var
  NewForm : TForm;
  RichEdit: TRichEdit;
    Edit  : TEdit;
  NewButton: TBitBtn;
  NewLabel: TLabel;
  AThread : TXThread;
begin
  NewForm := TForm.create(self);
  with NewForm do
  begin
    Left := 100;
    Top := 200;
    Width := 250;
    Height := 350;
    Caption := TreeView1.Selected.Text;
    Name   := 'Form'+TreeView1.Selected.Text;
    OnClose := CustomFormOnClose;
    Show;
  end;
  RichEdit:= TRichEdit.Create(Self);
  with RichEdit do
  begin
    Left := 5;
    Top := 5;
    Width := 180;
    Height := NewForm.Height - 60;
    text:= '';
    Name   := 'RichEdit'+TreeView1.Selected.Text;
    parent := NewForm;
  end;
  Edit:= TEdit.Create(Self);
  with Edit do
  begin
    Left := RichEdit.Left;
    Width := RichEdit.Width;
    Height := 300;
    Top := RichEdit.Height+10;
    Name   := 'Edit'+TreeView1.Selected.Text;
    text := '';
    parent := NewForm;
  end;
  NewButton:= TBitBtn.Create(Self);
  with NewButton do
  begin
    Left := edit.width + 10;
    Width := 50;
    Height := Edit.Height;
    Top := Edit.Top;
    Name   := 'BitBtn'+TreeView1.Selected.Text;
    Caption:= 'Send';
    OnClick:= BtnClickEv;
    parent := NewForm;
  end;
  NewLabel:= TLabel.Create(Self);
  with NewLabel do
  begin
    Left := edit.width + 30;
    Width := 50;
    Height := Edit.Height;
    Top := 30;
    Name   := 'Caption'+TreeView1.Selected.Text;
    Caption:= '0';
    parent := NewForm;
  end;
  AThread:= TXThread.Create(TreeView1.Selected, NewForm, NewLabel, NewButton);
  AThread.Name:= 'Thread'+ AThread.ThreadNode.Text;
  ThreadList.Add(AThread);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 ThreadList.Free;
end;

end.
ASKER CERTIFIED SOLUTION
Avatar of shaneholmes
shaneholmes

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
also Omar,

if you add a  Application.ProcessMessages; to the DoCount method, you will actually see the update to the label (instead of waiting until the loop is finished)

Shane

procedure TXThread.DoCount;
var
 I: Integer;
begin
 for I:= 0 to 10000 do
 begin
  FormLabel.Caption:= inttostr(I);
  Application.ProcessMessages;
 end;
end;
Avatar of omarmf

ASKER

Yes Mr Shane

  You are more carfull then the one who is doing actually the program

NewLabel:= TLabel.Create(Self);
  with NewLabel do
  begin
    Left := edit.width + 30;
    Width := 50;
    Height := Edit.Height;
    Top := 30;
    Name   := 'Caption'+TreeView1.Selected.Text;
    Caption:= '0';
    parent := NewForm;
  end;

put this will generate a new label called CaptionOmar as instance

I will make it

Name   := 'Label'+TreeView1.Selected.Text;

Put it is no problem

Thank you a lot