Solved

Help in delphi threading

Posted on 2011-03-03
25
703 Views
Last Modified: 2012-05-11
Hello experts.
Please help me.
Alloc me only 10 minutes, please.


please write me a simple delphi application that works with many threads.
I need the program scheleton.
But i dont know where to put my own procedure in thread.execute or in button.click?


please write me a simple app that works with threads (number of threads must be indicated in edit), and tell me where to put my procedure...
And tell me where to put my procedure (this connect to a site and parse a text) in thread.execute or button.click..
Please, everyone help me!
Thanks
0
Comment
Question by:helyonprime96
  • 9
  • 8
  • 6
  • +2
25 Comments
 
LVL 24

Expert Comment

by:jimyX
ID: 35029996
0
 
LVL 14

Expert Comment

by:systan
ID: 35030207
You need to understand the code for Delphi threading, before you can make your own,  just I was before.  Even now I strive hard to fully understand threading in Delphi.   Not like .Net is easy to implement.

Ok;
Look at the sample codes I send to you,  compare code lines.
Follow some steps here;
and understand it loudly

<from Freddy1990>
The easiest way is sublassing the TThread class.

uses Classes;
type
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;
  end;
...
procedure TMyThread.Create;
begin
  inherited Create(False);
  FreeOnTerminate := True;
end;

This example would start the thread instantly after creation and free it automatically on termination. You just put the code you want to execute in the Execute method.

If you want to interact with the main thread, you need to synchronize calls by adding a method to the thread without result or parameters and calling Synchronize on it, like Synchronize(Method);
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 35030250
how many processors do you have in your computer ?

if you have only 1, then there is almost no gain,
except for a more responsive front-end, the actual work will still take the same amount of time

if you have no knowledge about threading in delphi,
then start reading about the basics :
starting a thread, using protection objects to access shared resources, ending/cleaning up threads

i wrote a article about showing progress of a thread
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/A_239-Displaying-progress-in-the-main-form-from-a-thread-in-Delphi.html

it also provides a helper class for comunication
0
 

Author Comment

by:helyonprime96
ID: 35030288
yes, i make it all steps..
the thread.execute section is thread instructions
and the button1.click is the creation of thread.
When i debug it, i'm getting an error : ...check your template
and nothing happens..

Can someone help me?
0
 
LVL 14

Expert Comment

by:systan
ID: 35030395
Learn and understand from this link;
http://www.delphicorner.f9.co.uk/articles/db1.htm#Running%20Queries%20in%20Threads

TO Really understand Threads in Delphi;

Let's look at the TThread's structure.

Here's the declaration for the TThread object:

  TThread = class
  private
    FHandle: THandle;
    FThreadID: THandle;
    FTerminated: Boolean;
    FSuspended: Boolean;
    FMainThreadWaiting: Boolean;
    FFreeOnTerminate: Boolean;
    FFinished: Boolean;
    FReturnValue: Integer;
    FOnTerminate: TNotifyEvent;
    FMethod: TThreadMethod;
    FSynchronizeException: TObject;
    procedure CallOnTerminate;
    function GetPriority: TThreadPriority;
    procedure SetPriority(Value: TThreadPriority);
    procedure SetSuspended(Value: Boolean);
  protected
    procedure DoTerminate; virtual;
    procedure Execute; virtual; abstract;
    procedure Synchronize(Method: TThreadMethod);
    property ReturnValue: Integer read FReturnValue write FReturnValue;
    property Terminated: Boolean read FTerminated;
  public
    constructor Create(CreateSuspended: Boolean);
    destructor Destroy; override;
    procedure Resume;
    procedure Suspend;
    procedure Terminate;
    function WaitFor: Integer;
    property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;
    property Handle: THandle read FHandle;
    property Priority: TThreadPriority read GetPriority write SetPriority;
    property Suspended: Boolean read FSuspended write SetSuspended;
    property ThreadID: THandle read FThreadID;
    property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
  end;

Its structure is quite simple -- and simple is good

In most components there are only a few procedures and properties you need to think about; this is not an exception with TThread. The only methods you'll need to worry about are Execute, Create, and Synchronize; and the only property that you'll usually need to access is FreeOnTerminate.

Key Methods and Properties of TThread

The key methods and property of TThread are listed below in Table 1.

    Attribute: Create       Parameters: CreateSuspended: Boolean

        The Create method allocates memory, starts the thread and specifies the thread function in CreateThread as the Execute procedure. Here, as in any Create method, you can initialize vars and perform some preliminary operations. However, unlike a normal Create method, the thread is already executing by the time the method ends. Usually this isn't a problem because you'll just create the object and forget about it. But if you have to do any processing before the thread starts executing, set the CreateSuspended parameter to False. This allocates memory for the thread and sets it up, but the thread will not execute until you make a call to the Resume procedure. This is useful, especially if you need to set up values your thread will need over the course of its lifetime.

          
    Attribute: Execute       Parameters: None

        Execute is your TThread's central execution method. It's fairly synonymous with a main processing or central control procedure or function you might use to execute all the procedures in a particular unit. The only difference is that with a TThread object, the first method that is called must be called Execute. This doesn't mean that you can't call another procedure which acts in that capacity from Execute. It's definitely more convenient to put your execution code here because that's Execute's purpose.

        One important note: If you look in the object declaration of TThread, you'll see that it is declared as a virtual; abstract; method. This means it's not implemented in any way, shape or form; therefore, it's up to you to provide the code. And there's no inherited functionality, so you'll never make a call to inherited Execute; in your own implementation.

          
    Attribute: Synchronize       Parameters: Method: TThreadMethod

        Synchronize is your key to safely accessing the VCL in your thread. When Synchronize executes, your thread becomes a part of the main thread of the program, and in the process, suspends the operation of the main thread. This means the VCL can't receive messages from other threads other than the one you're synchronizing to the main thread, which in turn makes it safe to execute any VCL calls.

        Think of Synchronize as a middleman in a transaction. You have a buyer, which is the main thread of the program, and a seller of services, which is another thread of execution created within the same process. The seller would like to sell the buyer some goods -- in our case, do some operation on the VCL components running in the main thread -- but the buyer doesn't really know the seller, and is appalled at how the seller actually performs his service, so is afraid the seller's service may have a negative effect on him. So the seller enlists the help of an agent (the Synchronize procedure) to smooth things out, take the buyer out to lunch so the seller can do his thing.

        The seller is a procedure that performs the action on behalf of the thread. It doesn't have to be a specific type, but it must be a method of the thread. Say I have a long process running in a background thread that at certain times must update the text in a TPanel on the main form to give feedback about the thread's current status to the user. If I wrote in my code Form1.Panel1.Caption := 'This is my update message', I'd raise an exception -- most likely an access violation error. But if I encapsulate the call in a procedure, then call Synchronize, the message will be sent and text will be updated. Synchronize acted as a middleman so my status message could be passed to the TPanel.

        I've may have confused rather than enlightened you! Just remember this:

            When you want to call VCL objects from another thread, create a wrapper procedure for the operations you want to carry out, then use Synchronize to synchronize your thread with the main thread so your call can be safely executed.

        Synchronize is meant to be used really quickly. Execute it, then get out of it as soon as you can. While Synchronize is running, you essentially have only one thread working. The main thread is suspended.

          
    Attribute: FreeOnTerminate       Parameters: Set property to Boolean value

        This is a really useful property. Typically, once your execute procedure finishes, the Terminated Boolean property is set to False. However, the thread still exists. It's not running, but it's taking up space, and it's up to you to free the thread. But by setting this property in the Create constructor to True, the thread is immediately freed -- and with it, all the resources it took up -- after it's finished executing.


for other links if you want advance;
http://delphi.about.com/od/kbthread/Threading_in_Delphi.htm
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 35030399
you can't debug a thread, it doesn't work

show your code, only then can we help
0
 

Author Comment

by:helyonprime96
ID: 35030428
ok.this is my code :
 
unit Unit2;

interface

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

  type
TSafeSampleThread = class(TThread)
  private 
    FLocalVariable: Integer;
  protected 
  public 
    procedure Execute; override;
  end;

type
  TForm2 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    YaTic1: TYaTic;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    procedure ThreadDone(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TSafeSampleThread.Execute; 
var
  I: Integer;
  first : integer;
  last : integer;
  current : integer;
  i2 : integer;
begin 
  for I := 1 to form2.Memo1.Lines.Count do
  begin
    Application.ProcessMessages;
    try
            first := 1;
 last :=  form2.memo2.Lines.Count;
 Current := 1;
  for I2 := 1 to  form2.Memo2.Lines.count do
 begin
  inc(current);
  form2.YaTic1.URL:= form2.Memo2.Lines[current];
 form2.Memo1.Lines.Add( form2.memo2.Lines[current]  + '  ' + 'TIC : ' + Inttostr( form2.Yatic1.TIC) + '  ' + ' PR: ' + Inttostr( form2.YaTic1.Rang) );
end;
      Application.ProcessMessages; 
      Inc(FLocalVariable); 
      Application.ProcessMessages;

    finally

    end; 
  end; 
end;

procedure TForm2.ThreadDone(Sender: TObject);
begin
  Label1.Caption := 'gata';
end;

procedure TForm2.Button1Click(Sender: TObject);
begin

 with TSafeSampleThread.Create(False) do
        OnTerminate := ThreadDone;

end;

end.

Open in new window


help please.
0
 
LVL 14

Expert Comment

by:systan
ID: 35030444
For better solution, post your whole project code here; there's no need to worry.
jimyX, ewangoya, geert will step a help for you.
0
 
LVL 14

Expert Comment

by:systan
ID: 35030473
Sorry, late posting it.

That's good.
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 35030482
systan,
are we your employees ?

please stop acting like you were our employer
0
 

Author Comment

by:helyonprime96
ID: 35030490
what good?

my code doesnt working.
Can you suggest how can i work with indy idthreadcomponent?
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 35030552
i'll try and point out the problems:

step by step:
1: pass the info to thread before it starts
 
... yuh ... what are you trying to do ???

what is memo1 for and what is memo2 for

why do you use a for loop on memo1 and then also add lines to memo1 ?
what's in both memo's ????
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 35030569
you want to get text from list of websites (urls) and put that in a other memo ?

0
 

Author Comment

by:helyonprime96
ID: 35030606
yes, sure
0
 

Author Comment

by:helyonprime96
ID: 35030612
i'll try to use indy threadcomponent, but nothing happens with it.
only errors.
0
 
LVL 36

Accepted Solution

by:
Geert Gruwez earned 500 total points
ID: 35031273
very simple demo of threading model:
code:
unit Unit1;

interface

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

type
  TFeedbackProc = procedure (Sender: TObject; Url, Text: string) of object;

type
  TForm1 = class(TForm)
    pnlTop: TPanel;
    memUrls: TMemo;
    pnlOptions: TPanel;
    btnStart: TButton;
    pnlOutput: TPanel;
    memOutput: TMemo;
    lblOutput: TLabel;
    lblUrls: TLabel;
    procedure btnStartClick(Sender: TObject);
  private
    procedure ThreadFeedback(Sender: TObject; aUrl, aOutput: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
  TWorkThread = class(TThread)
  private
    fUrls: TStrings;
    fFeedback: TFeedbackProc;
    fUrl: string;
    fText: string;
  protected
    procedure SendFeedback;
    procedure Execute; override;
  public
    constructor Create(aUrls: TStrings; aFeedback: TFeedbackProc);
    destructor Destroy; override;
  end;

{ TWorkThread }

constructor TWorkThread.Create(aUrls: TStrings; aFeedback: TFeedbackProc);
begin
  inherited Create(False);
  fUrls := TStringList.Create;
  if Assigned(aUrls) then
    fUrls.Assign(aUrls);
  fFeedback := aFeedback;
end;

destructor TWorkThread.Destroy;
begin
  FreeAndNil(fUrls);
  inherited;
end;

procedure TWorkThread.Execute;
var I: Integer;
begin
  for I := 0 to fUrls.Count-1 do
  begin
    fUrl := fUrls[I];
    // Do something with your url here
    fText := 'Get Text of "' + fUrl + '"';
    Synchronize(SendFeedback);
  end;
  fUrl := '';
  fText := 'Done';
  Synchronize(SendFeedback);
end;

procedure TWorkThread.SendFeedback;
begin
  if Assigned(fFeedback) then
    fFeedback(Self, fUrl, fText);
end;

procedure TForm1.btnStartClick(Sender: TObject);
begin
  TWorkThread.Create(memUrls.Lines, ThreadFeedback);
end;

procedure TForm1.ThreadFeedback(Sender: TObject; aUrl, aOutput: string);
begin
  memOutput.Lines.Add('url: ' + aUrl);
  memOutput.Lines.Add('text: ' + aOutput);
end;

end.

Open in new window


dfm:
object Form1: TForm1
  Left = 188
  Top = 81
  Caption = 'Form1'
  ClientHeight = 536
  ClientWidth = 971
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object pnlTop: TPanel
    Left = 0
    Top = 0
    Width = 971
    Height = 257
    Align = alTop
    TabOrder = 0
    ExplicitLeft = 8
    ExplicitTop = 32
    ExplicitWidth = 825
    object lblUrls: TLabel
      Left = 1
      Top = 42
      Width = 969
      Height = 13
      Align = alTop
      Alignment = taCenter
      Caption = 'List of urls'
      ExplicitWidth = 49
    end
    object memUrls: TMemo
      Left = 1
      Top = 55
      Width = 969
      Height = 201
      Align = alClient
      Lines.Strings = (
        'url 1'
        'url 2'
        'url 3'
        'url 4'
        'url 5'
        'url 6'
        'url 7')
      TabOrder = 0
      ExplicitLeft = 24
      ExplicitTop = 39
      ExplicitWidth = 369
      ExplicitHeight = 145
    end
    object pnlOptions: TPanel
      Left = 1
      Top = 1
      Width = 969
      Height = 41
      Align = alTop
      BevelOuter = bvNone
      TabOrder = 1
      ExplicitLeft = 432
      ExplicitTop = 24
      ExplicitWidth = 185
      object btnStart: TButton
        Left = 24
        Top = 8
        Width = 75
        Height = 25
        Caption = 'Start thread'
        TabOrder = 0
        OnClick = btnStartClick
      end
    end
  end
  object pnlOutput: TPanel
    Left = 0
    Top = 257
    Width = 971
    Height = 279
    Align = alClient
    BevelWidth = 4
    TabOrder = 1
    ExplicitLeft = 64
    ExplicitTop = 336
    ExplicitWidth = 353
    ExplicitHeight = 121
    object lblOutput: TLabel
      Left = 4
      Top = 4
      Width = 963
      Height = 13
      Align = alTop
      Alignment = taCenter
      Caption = 'Output'
      ExplicitLeft = 128
      ExplicitTop = 16
      ExplicitWidth = 34
    end
    object memOutput: TMemo
      Left = 4
      Top = 17
      Width = 963
      Height = 258
      Align = alClient
      TabOrder = 0
      ExplicitLeft = 32
      ExplicitTop = 56
      ExplicitWidth = 185
      ExplicitHeight = 89
    end
  end
end

Open in new window

0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 35031276
it takes more than 10 minutes to write code
0
 

Author Comment

by:helyonprime96
ID: 35031560
thanks a lot
0
 

Author Comment

by:helyonprime96
ID: 35031602
why i cannot use idhttp in execute?
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 35031737
are you new to delphi ?
0
 
LVL 36

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 500 total points
ID: 35031824
you can use idhttp, it's not a visual component
> any component you can put on a datamodule is a non-visual component (in 90% of the time)

i never said you can't use idhttp in execute
here is sample with idhttp in execute
 
procedure TWorkThread.Execute;
var
  aIdHTTP: TIdHTTP;
  I: Integer;
  s: TStringStream;
begin
  aIdHTTP := TIdHTTP.Create(nil);
  try
    aIdHTTP.AllowCookies := True;
    aIdHTTP.HTTPOptions := [hoForceEncodeParams];
    s := TStringStream.Create;
    try
      for I := 0 to fUrls.Count-1 do
      begin
        fUrl := fUrls[I];
        // Do something with your url here
        s.Clear;
        aIdHTTP.Get(fUrl, s);
        s.Seek(0, soFromBeginning);
        fText :=  'Get Text of "' + s.DataString + '"';
        Synchronize(SendFeedback);
      end;
    finally
      FreeAndNil(s);
    end;
  finally
    FreeAndNil(aIdHttp);
  end;
  fUrl := '';
  fText := 'Done';
  Synchronize(SendFeedback);
end;

Open in new window

0
 
LVL 14

Expert Comment

by:systan
ID: 35033478
systan,
are we your employees ?

please stop acting like you were our employer

Oh, man, don't get it wrong, just drink the beer.

Ok, I'll never say that again, sorry.

But to tell you frankly, I just believed that you guys here are very good, that's why I said that.

listening ...
0
 

Author Closing Comment

by:helyonprime96
ID: 35034926
thanks
0
 
LVL 32

Expert Comment

by:ewangoya
ID: 35040451

Systan, never mind Geert
He is always grumpy before he takes one
0
 
LVL 14

Expert Comment

by:systan
ID: 35041502
k
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

A short article about a problem I had getting the GPS LocationListener working.
Entering a date in Microsoft Access can be tricky. A typo can cause month and day to be shuffled, entering the day only causes an error, as does entering, say, day 31 in June. This article shows how an inputmask supported by code can help the user a…
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

760 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

19 Experts available now in Live!

Get 1:1 Help Now