Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Property Read Property write ??

Posted on 2004-09-25
18
Medium Priority
?
353 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
ID: 12153507
Add:

   NewThread.OnTerminate        := YourVCLClass.Fine;

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

Author Comment

by:Balshe
ID: 12153530
i know this but onterminate is used by another Procedure

NewThread.OnTerminate :=Update_LISTS;







0
 
LVL 1

Author Comment

by:Balshe
ID: 12153536
do you think there is a way to pass the parameters from the thread to the main thread other than that?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 4

Expert Comment

by:Delphian
ID: 12153727
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
ID: 12153746
how is that?
0
 
LVL 4

Expert Comment

by:ceoworks
ID: 12154465
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
ID: 12156449
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
ID: 12157181
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
ID: 12157861
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
 
LVL 17

Expert Comment

by:geobul
ID: 12158357
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
ID: 12158692
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
ID: 12158729
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 600 total points
ID: 12159181
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
ID: 12159194
Do you need source project files too ?
0
 
LVL 1

Author Comment

by:Balshe
ID: 12159766
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 1400 total points
ID: 12161224
// 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
ID: 12167368
Thanks to you all guys

special thanks to  geobul and ceoworks




0
 
LVL 1

Author Comment

by:Balshe
ID: 12167396
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

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
This video shows how to quickly and easily deploy an email signature for all users in Office 365 and prevent it from being added to replies and forwards. (the resulting signature is applied on the server level in Exchange Online) The email signat…
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses

876 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