• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 354
  • Last Modified:

Property Read Property write ??

hi all


i have a main program that generates Threads :

...
...
...


 NewThread :=un_Process_Thread.Create(True);
 NewThread.FreeOnTerminate := True;
 NewThread.File_NO :=files_Array[i-1].File_ID; // this is who the main thread passes data to the other threads

...
...
...


no how can i read data from the thread?
i need that because i should know when the thread has finished processing ,what file was is processing and then in the main thread i should update the status of the file.


and is property read and property write helpfull in this? and if it is can any one show me a small example ?



















0
Balshe
Asked:
Balshe
  • 9
  • 4
  • 2
  • +2
2 Solutions
 
ginsonicCommented:
Add:

   NewThread.OnTerminate        := YourVCLClass.Fine;

On this procedure can know when thread has finished processing......
0
 
BalsheAuthor Commented:
i know this but onterminate is used by another Procedure

NewThread.OnTerminate :=Update_LISTS;







0
 
BalsheAuthor Commented:
do you think there is a way to pass the parameters from the thread to the main thread other than that?
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
DelphianCommented:
You could create a property or field on
the thread class and use this to get the
results.

[]s Delphian
0
 
BalsheAuthor Commented:
how is that?
0
 
ceoworksCommented:
Hi Balshe,

It's not so safe to reach to the thread's properties like this. I would suggest you to use SendMessage API with WM_COPYDATA struct. Take a look at the accepted answers :

http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20434236.html
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20280702.html

These solutions can be usefull for you to understand the usage of WM_COPYDATA.

Regards,

Oktay Sancak
0
 
DelphianCommented:
Not safe? Please elaborate, because is the first time I heard
that it is not safe to pool the threads' properties...
0
 
ceoworksCommented:
Ohh maybe i gave a quick answer without to understand this question properly :( I was talking about the conditions we need to use(change/modify) the same data from the inside and outside of the thread. So i suggested something useless.. Sorry about it. OK, Now i think that i understand the question so let's take a look at this example code that i wrote for you :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

const
  EVNT_THREAD_FINISHED = WM_USER + 7; // our custom message

type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    // for to trap our custom messages which let us to know that our thread finished :
    procedure OnMyMessage(var Msg: TMessage); message EVNT_THREAD_FINISHED;
  end;

  TMyCustomThread = class(TThread)
  private
    FOwnerHandle: HWND;
  protected
    procedure Execute; override;
  public
    // some other functions, properties or procedures here
    constructor Create(AOwnerHandle: HWND);
    destructor Destroy; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.OnMyMessage(var Msg: TMessage);
begin
  Caption := 'Thread Finished';
end;

{ TMyCustomThread }

constructor TMyCustomThread.Create(AOwnerHandle: HWND);
begin
  FOwnerHandle := AOwnerHandle;
  inherited Create(True); // or False..
  FreeOnTerminate := True;
end;

procedure TMyCustomThread.Execute;
begin
  inherited;

end;

destructor TMyCustomThread.Destroy;
begin
  SendMessage(FOwnerHandle, EVNT_THREAD_FINISHED, 0, 0); // here we let our main form to know that our thread is finished running..
  inherited;
end;

end.

All the thing you need to do is :

var
  MyThread: TMyCustomThread;    
begin
  MyThread := TMyCustomThread.Create(Form1.Handle); // now your thread knows where to send the messages
  // do something
end;

Sorry about my irrelevant answer. Delphian, thanks for to wake me up :)

Kind Regards,

Oktay
0
 
BalsheAuthor Commented:
guys though what is above is understandable and applicable but i think what i need is more simple than this


lets say [A] is the main thread ,and [B1] is one of the threads thar are executing


on [A] there is something like :

        [A]. OnTerminate        := Run_Procedure_WITH_VARIABLES_FROM_B;


Or lets say [A] has array of record called FILES_ARRAY , and this is how the record looks like:
           File_ID:Integer
           Status:Integer;


before [A] Starts ,it gives it the value to a variable in thread [B] ; and [B] starts processing this value.
  Ex: //This is  on [A]
         [B].File_ID :=files_Array[I].File_ID;
         [B].File_INDX:=I;
         [B].OnTerminate :=Update_THREAD_COUNT;
         [B].Resume;

now when [B] finishes processing this Value ,it's gonna update it's status in the array "FILES_ARRAY" declared in [A]
 Ex:  // this is on [B]
        [A].files_array[file_INDX].Stats:=2;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
how am i supposed to declare those variables  :


     Files_Array       on[A]
     File_ID             on[B]
     File_INDX         on[B]
0
 
geobulCommented:
Hi,

ceoworks code will do what you need with some little additions:

1. Pass File_ID as a parameter in SendMessage:

destructor TMyCustomThread.Destroy;
begin
  SendMessage(FOwnerHandle, EVNT_THREAD_FINISHED, File_ID, 0); // here we let our main form to know that our thread is finished running..
  inherited;
end;

2. Call 'Update_THREAD_COUNT' in procedure 'OnMyMessage' and not in Thread.OnTerminate. (Do not assign Thread.OnTerminate !)

procedure TForm1.OnMyMessage(var Msg: TMessage);
var File_ID_JustProcessed: integer;
begin
  File_ID_JustProcessed := Msg.wParam;
  Update_THREAD_COUNT(File_ID_JustProcessed); // uses File_ID_JustProcessed to update its status in the array
end;

3. Start a new thread like this:

MyThread := TMyCustomThread.Create(Form1.Handle);
MyThread.File_ID := files_Array[I].File_ID;
MyThread.File_INDX := I;
MyThread.Resume;

Hope it becomes more clear now. Using such approach looks better to me because all actions on form's controls (updating counters and changing files status) are being executed by the main thread.

Regards, Geo
0
 
BalsheAuthor Commented:
guys could and one send me a source code to my email ,i'm raising the points to 700
 
my email is balshe2000@yahoo.com


thanks
0
 
BalsheAuthor Commented:
i just found that the maximum is 500 :)
any way i could ask any question and put 200 on it






0
 
ceoworksCommented:
Here is an example :

--------------

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

const
  EVNT_THREAD_FINISHED = WM_USER + 7; // our custom message

type
  TForm1 = class(TForm)
    btnStart: TButton;
    btnTerminate: TButton;
    procedure btnStartClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnTerminateClick(Sender: TObject);
  private
    { Private declarations }
  public
    procedure OnMyMessage(var Msg: TMessage); message EVNT_THREAD_FINISHED;
  end;

  TMyThread = class(TThread)
  private
    X, Y: integer;
    FOwnerHandle: HWND;
    procedure UpdateDots;
  protected
    procedure Execute; override;
  public
    constructor Create(AOwnerHandle: HWND);
    destructor Destroy; override;
  end;

var
  Form1: TForm1;
  MyThread: TMyThread;

implementation

uses Math;

{$R *.dfm}

{ TMyThread }

constructor TMyThread.Create(AOwnerHandle: HWND);
begin
  FOwnerHandle := AOwnerHandle;
  inherited Create(False);
  FreeOnTerminate := True;
end;

destructor TMyThread.Destroy;
begin
  SendMessage(FOwnerHandle, EVNT_THREAD_FINISHED, X, Y);
  inherited;
end;

procedure TMyThread.Execute;
begin
  inherited;
  repeat
    X := Random(100);
    Y := Random(100);
    Synchronize(UpdateDots);
  until Terminated;
end;

procedure TMyThread.UpdateDots;
begin
  Form1.Canvas.Pixels[X, Y] := clRed;
end;

procedure TForm1.btnStartClick(Sender: TObject);
begin
  MyThread := TMyThread.Create(Form1.Handle);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  MyThread.Terminate;
end;

procedure TForm1.btnTerminateClick(Sender: TObject);
begin
  MyThread.Terminate;
end;

procedure TForm1.OnMyMessage(var Msg: TMessage);
begin
  Form1.Caption := 'Thread terminated at the pixer of Y: ' + IntToStr(Msg.LParam) + ' X: ' + IntToStr(Msg.WParam);
end;

end.

--------------
0
 
ceoworksCommented:
Do you need source project files too ?
0
 
BalsheAuthor Commented:
guys i'm really sorry ,but i'm new to Delphi
can i have an example that has two units ,one is the main thread (Main form that lunches the threads) and the other one is the thread it self?



0
 
geobulCommented:
// main form
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

const
  EVNT_THREAD_FINISHED = WM_USER + 7; // our custom message

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure OnMyMessage(var Msg: TMessage); message EVNT_THREAD_FINISHED;
    procedure Update_THREAD_COUNT(File_ID: integer);
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses unit2;

procedure TForm1.OnMyMessage(var Msg: TMessage);
var File_ID_JustProcessed: integer;
begin
  File_ID_JustProcessed := Msg.wParam;
  Update_THREAD_COUNT(File_ID_JustProcessed); // uses File_ID_JustProcessed to update its status in the array
end;

procedure  TForm1.Update_THREAD_COUNT(File_ID: integer);
begin
  ShowMessage('file '+ IntToStr(File_ID) + ' has been processed');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MyCustomThread := TMyCustomThread.Create(Form1.Handle);
  MyCustomThread.File_ID := 7;
  MyCustomThread.File_INDX := 2;
  MyCustomThread.Resume;
end;

end.
-------------
// thread
unit Unit2;

interface

uses
  Windows, Messages, Classes;

const
  EVNT_THREAD_FINISHED = WM_USER + 7; // our custom message

type

TMyCustomThread = class(TThread)
  private
    FOwnerHandle: HWND;
  protected
    procedure Execute; override;
  public
    File_ID: integer;
    File_INDX: integer;
    constructor Create(AOwnerHandle: HWND);
    destructor Destroy; override;
  end;

var
  MyCustomThread: TMyCustomThread;

implementation

constructor TMyCustomThread.Create(AOwnerHandle: HWND);
begin
  FOwnerHandle := AOwnerHandle;
  inherited Create(True); // or False..
  FreeOnTerminate := True;
end;

procedure TMyCustomThread.Execute;
begin
  // do whatever you need here
  // ...
end;

destructor TMyCustomThread.Destroy;
begin
  SendMessage(FOwnerHandle, EVNT_THREAD_FINISHED, File_ID, 0);
  inherited;
end;

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

Regards, Geo
0
 
BalsheAuthor Commented:
Thanks to you all guys

special thanks to  geobul and ceoworks




0
 
BalsheAuthor Commented:
ceoworks
you could collect the rest of your point on this link

http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21147508.html

thanks
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 9
  • 4
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now