Solved

Property Read Property write ??

Posted on 2004-09-25
18
344 Views
Last Modified: 2012-05-05
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
Comment
Question by:Balshe
  • 9
  • 4
  • 2
  • +2
18 Comments
 
LVL 9

Expert Comment

by:ginsonic
Comment Utility
Add:

   NewThread.OnTerminate        := YourVCLClass.Fine;

On this procedure can know when thread has finished processing......
0
 
LVL 1

Author Comment

by:Balshe
Comment Utility
i know this but onterminate is used by another Procedure

NewThread.OnTerminate :=Update_LISTS;







0
 
LVL 1

Author Comment

by:Balshe
Comment Utility
do you think there is a way to pass the parameters from the thread to the main thread other than that?
0
 
LVL 4

Expert Comment

by:Delphian
Comment Utility
You could create a property or field on
the thread class and use this to get the
results.

[]s Delphian
0
 
LVL 1

Author Comment

by:Balshe
Comment Utility
how is that?
0
 
LVL 4

Expert Comment

by:ceoworks
Comment Utility
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
 
LVL 4

Expert Comment

by:Delphian
Comment Utility
Not safe? Please elaborate, because is the first time I heard
that it is not safe to pool the threads' properties...
0
 
LVL 4

Expert Comment

by:ceoworks
Comment Utility
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
 
LVL 1

Author Comment

by:Balshe
Comment Utility
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
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 17

Expert Comment

by:geobul
Comment Utility
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
 
LVL 1

Author Comment

by:Balshe
Comment Utility
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
 
LVL 1

Author Comment

by:Balshe
Comment Utility
i just found that the maximum is 500 :)
any way i could ask any question and put 200 on it






0
 
LVL 4

Assisted Solution

by:ceoworks
ceoworks earned 150 total points
Comment Utility
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
 
LVL 4

Expert Comment

by:ceoworks
Comment Utility
Do you need source project files too ?
0
 
LVL 1

Author Comment

by:Balshe
Comment Utility
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
 
LVL 17

Accepted Solution

by:
geobul earned 350 total points
Comment Utility
// 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
 
LVL 1

Author Comment

by:Balshe
Comment Utility
Thanks to you all guys

special thanks to  geobul and ceoworks




0
 
LVL 1

Author Comment

by:Balshe
Comment Utility
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

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now