Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Create a Thread that you can send values with.

Posted on 2010-09-03
23
Medium Priority
?
499 Views
Last Modified: 2012-06-21
Hi, is it possible to create a thread that you can send values with.

because I'm wanting to have about 5++ threads open at the same time updating different things within the listview at the same time. and it doesn't have to be restricted to the listview, it can be updating into a memo, though without freezing up the app.

is it possible? if so could anyone provide links/examples/functions/files etc. if you've created it in delphi, would u provide the pas and dfm.
0
Comment
Question by:eNarc
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 5
  • 4
  • +2
23 Comments
 
LVL 25

Accepted Solution

by:
epasquier earned 400 total points
ID: 33597110
each thread accessing VCL would have to synchronize with the main thread. Synchronization is the fact that 2 threads will lock one another while one is accessing shared data, so that no 2 threads read/write the same data at the same time, thus causing all sorts of errors.

This can be done with messages : all threads posting data to update to main thread which is then the only one to access the VCL components.

but Delphi has a convenient way of synchronizing without needing to handle all kinds of thread messages : it's the Synchronize feature.

basically, you just add Synchronize( )  around a procedure call in your thread, and this procedure will be the one accessing VCL. This procedure will be executed BY THE MAIN THREAD, and your origin thread is suspended until it's done.

Ex :

procedure TMyThread.UpdateVCL;
begin
 frmMain.ListBox.Items.Add(NewValue);
end;

procedure TMyThread.AddValue(aValue:String);
begin
 NewValue:=aValue; // New Value is a global or public property of TMyThread
 Synchronize(UpdateVCL);
end;

It is even probable that the synchronized procedure can have parameters, therefore removing the need to pass parameters as globals/public properties. I just haven't played enough, nor gone too deep in the Delphi code to be sure.
0
 
LVL 5

Author Comment

by:eNarc
ID: 33597298
where does the NewValue come from and how can I send it?
0
 
LVL 5

Author Comment

by:eNarc
ID: 33597403
getting errors not recognized.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 32

Assisted Solution

by:Ephraim Wangoya
Ephraim Wangoya earned 400 total points
ID: 33597474
Heres an exmple epanding on epasquires comment

unit Unit1;

interface

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

type
  TMyProcedure = procedure(const AValue: string) of object;

  TMyThread = class(TThread)
  private
    FValue: string;
    FMyProc: TMyProcedure;
    procedure DoProc;
  public
    constructor Create(AProc: TMyProcedure);
    procedure Execute; override;
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    procedure UpdateList(const AValue: string);
    procedure UpdateMemo(const AValue: string);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  TMyThread.Create(UpdateList);
  TMyThread.Create(UpdateMemo);
end;

{ TMyThread }

constructor TMyThread.Create(AProc: TMyProcedure);
begin
  inherited Create(True);
  FreeOnTerminate := True;
  FMyProc := AProc;
  Resume;
end;

procedure TMyThread.DoProc;
begin
  if Assigned(FMyProc) then
    FMyProc(FValue);
end;

procedure TMyThread.Execute;
var
  I: Integer;
begin
  for I := 1 to 10 do
  begin
    FValue := IntToStr(I);
    Synchronize(DoProc);
    sleep(1000);
  end;
end;

procedure TForm1.UpdateList(const AValue: string);
begin
  ListBox1.Items.Add(AValue)
end;

procedure TForm1.UpdateMemo(const AValue: string);
begin
  Memo1.Lines.Add(AValue);
end;

end.
0
 
LVL 25

Expert Comment

by:epasquier
ID: 33597486
of course you have to declare it. But ok, try calling the synchronized procedure with parameters. I really think it will work, I just don't remember and don't have time opening a project to test it.
procedure TMyThread.UpdateVCL(aValue:String);
begin
 frmMain.ListBox.Items.Add(aValue);
end;

procedure TMyThread.AddValue(aValue:String);
begin
 Synchronize(UpdateVCL(aValue));
end;

Open in new window

0
 
LVL 25

Expert Comment

by:epasquier
ID: 33597501
of course this is just a sample, you don't have to duplicate each such methods and usually will call directly Synchronize(Something) in your Execute function
0
 
LVL 32

Expert Comment

by:Ephraim Wangoya
ID: 33597541
@epasquire

Synchronize does not work with parameters
0
 
LVL 25

Expert Comment

by:epasquier
ID: 33597688
yeah, I wasn't too sure about it. I KNOW I've seen it in some post, but never tested, maybe it was just a simplification to better explain an algo without too much getting into details.

But really, if you think how Synchronize works (it post a message with the object of the method called, and the address of the method - then the main thread use these info to make the call and return a message to say it's done) it could also add the parameters to the message. So I wouldn't bet it is impossible and maybe some Delphi versions can do it (or will)
0
 
LVL 32

Expert Comment

by:Ephraim Wangoya
ID: 33597751
I've been waiting for that functionality for a very long time. It would surely simplify alot of code. I'm not sure why its never been implemented.
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 33598022
From D2009 onwards you can pass an anonymous method to Synchronize, thus eliminating the need for a global variable
0
 
LVL 5

Author Comment

by:eNarc
ID: 33600879
any examples/links/pas&dfm of it working would be great.
0
 
LVL 5

Author Comment

by:eNarc
ID: 33600911
you know how you can pass things through with a function, though in a function you have to wait until it ends, to begin another.

same thing though able to open and close on its own. with like 5++ running at the same time. and able to pass info through it so it does its job.
0
 
LVL 38

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 1200 total points
ID: 33605656
there is also a delphi article which passes values back through a callback procedure
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/A_239-Displaying-progress-in-the-main-form-from-a-thread-in-Delphi.html

the callback gets called from the synchronized method
it's up to the owner of the callback what to do with the information
it's not up to the thread

it's a common mistake to update vcl objects from within the thread
it makes the threads dependant on the form
this should not be the case

if you have to use "uses MainForm" in your thread, then that's using the thread to update the mainform
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 33609183
if you want different threads to post data back to the vcl
you could use a intermediate thread which channels all this data
there will allways be a bottleneck if you need to go from a multiple to a single

the threads posting to the intermediate thread would not have to wait for vcl
but they would have to wait on the sync object to add data in intermediate thread
this can cause a problem if the secondary threads can produce data faster than the intermediate thread can process
0
 
LVL 5

Author Comment

by:eNarc
ID: 33612167
Thanks aikimark makes more sense now hehe :P
0
 
LVL 5

Author Comment

by:eNarc
ID: 33612173
http:#33609183 Geert_Gruwez

mostly I'm after a function that u can send and it doesn't have to wait for it to end before activating another function.
0
 
LVL 5

Author Comment

by:eNarc
ID: 33612223
at the moment I'm using simply this to do the task, though its just on 1 thing.



procedure TForm1.ListView1Edited(Sender: TObject; Item: TListItem; var S: string);
procedure SaveThread(use : Pointer) ;
begin
  sleep(100);
  Save;
end;
var
  Thid:dword;
begin
  CreateThread(nil, 0, @SaveThread, nil, 0, thid);
end;


though I just can't send anything with it, it does 1 task and 1 task alone. only reason why I use the above is because when editing the listview, it would load the save before actually applying the edit to the listview, so sending it in a thread so it detaches from the procedure, and then within 100 it will then begin the save, saying the edit properly.

though really I'd like a function that I can send that is independent of the procedure once activated, than waiting for that to finish before beginning the next......
0
 
LVL 5

Author Comment

by:eNarc
ID: 33612232
why isn't independent functions/procedures standard? cos it seems like everyone would have a use for it.
0
 
LVL 38

Expert Comment

by:Geert Gruwez
ID: 33615268
well ... ugh ... not waiting .. but you are using sleep ???
what is that good for ?

you will need to elaborate
and post a snippet of inside your thread

is the thread you want to send info back from
or do you just want to launch a thread
or do you want to put something on a queue for a thread to proces ?
0
 
LVL 38

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 1200 total points
ID: 33615469
if you want to know about threads:

check the site for omnithread of the DelphiGeek
http://www.thedelphigeek.com/

and specific for his threading:
http://www.thedelphigeek.com/search/label/OmniThreadLibrary
0
 
LVL 5

Author Comment

by:eNarc
ID: 33616475
http:#33615268 Geert_Gruwez

>>well ... ugh ... not waiting .. but you are using sleep ???
sleeped to give the listview time to apply the edit, before saving, test it for yourself with listview and editing the caption when you click on it and then press enter, it runs the edit before it applys the edit, making the edit useless., it should be called BeforeEdit... than Edit...

>>what is that good for ?
absolutely everything.

>>you will need to elaborate
in what way?

>>and post a snippet of inside your thread
regardless of the snippet inside the thread, merely allowing a function to work independently from that of the executioner..


so for example with a procedure like so
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
for i:= 0 to listview1.items.count - 1 do//5 items
  Search(listview1.items[i].caption,*.*',listview1.items[i]);//'C:\
//  Search(,*.txt');//'E:\'
//  Search(,*.dfm');//'F:\'
//  Search(',*.pas');//'G:\
//  Search(',*.exe');//'H:\

end;

and boom, it activates all 5 at once allowing for individual updating and searching of all hard drives at once, this is just 1 useful way of using it.

>>is the thread you want to send info back from
sending information back isn't really important as it will execute independently of what started it making it impossible to return a result.

>>or do you just want to launch a thread
yea, executing it and allowing it to do its thing in its own time separate from what called it. so the application doesn't have to wait for it to finish, it can execute it and then have that running in the background while the application is free to do other useful things.

>>or do you want to put something on a queue for a thread to proces ?
a queue would be handy at times, like for example you only wanting to activate 5 threads though u have 10 threads being activated, queuing those extra 5 would be great.


0
 
LVL 38

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 1200 total points
ID: 33616787
you are indeed looking for a queued system
the delphi geek has actually the state of the art what you are looking for

i have to admit, it is complex
he has posted a webinar about it
http://video.vdug.org/2010/July/OmniThread%20Library_controller.swf

you might want to check the indy code for the threading
also a very extensive resource

because of this complexity i created my own system (less complex, and a lot less functionality)
it's a basic threading system
check this question:
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_26193383.html
and bugfix:
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_26193383.html#32794882

the basics for working with threads are:
1: start the thread in the vcl and give it a handle to post info back to a processing system
2: give the thread *everything* it needs to do it's job, without the need for other VCL object interaction
 * 3: if you can't do it with item 2, then use syncro objects to access all the shared resources
4: if necessary let the thread post back information (and don't update any vcl objects from within the thread)
5: if you receive loads of info from multiple threads, summarize first and then update the vcl
6: build in a cancel or kill for the thread so you can instantly close app, otherwise display the closing progress to the user
7: keep in mind, programming with threads is not easy, debugging is even more complex
8: provide a message file logging which you can switch on and off inside the threads/app
 
so in your case
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
for i:= 0 to listview1.items.count - 1 do//5 items
  Search(listview1.items[i].caption,*.*',listview1.items[i]);//'C:\
//  Search(,*.txt');//'E:\'
//  Search(,*.dfm');//'F:\'
//  Search(',*.pas');//'G:\
//  Search(',*.exe');//'H:\
end;

the thread searches the files, and then gathers all the info in a thread local variable (a stringlist ?)
when finished it then sends a message to the message processing procedure with the results
in the processing procedure you can then gather all needed info about the results
and if this procedure is synchronized, update the listview (using beginupdate and endupdate)

it's basically what that question is about
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

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

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
In this video, Percona Solutions Engineer Barrett Chambers discusses some of the basic syntax differences between MySQL and MongoDB. To learn more check out our webinar on MongoDB administration for MySQL DBA: https://www.percona.com/resources/we…
Suggested Courses

722 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