?
Solved

Delphi Multitasking (several codes running at same time)

Posted on 2003-12-02
8
Medium Priority
?
1,629 Views
Last Modified: 2007-12-19
I just wonder about a thing. I'm making a program which must be able to do several things at SAME time. Which means, one thing is the Application.ProcessMessages. For the application to not hang when doing some operations (like sending email). Lets say if I want to copy a 4 files on 200 megabyte in the app, and want the application to behave normally (like Outlook, Winzip, etc... when they do something which takes time) while copying. That means that I have to do these loops at SAME time:

//***For updating app:***
Repeat
  Application.ProcessMessages;
Until cancelupdate;


//***And this for the copying itself for example ***
For file := 0 to 4 do
begin
  filename :='C:\file'+inttostr(file)+'.zip';
  newfilename := 'C:\file'+inttostr(file)+'_new.zip';
  If FileExists(filename) Then
  begin
    CopyFile(filename,newfilename,false);
  end;
end;


Since the last one will take about 20 seconds, then the application can't seems like it has crashed in the meantime, and if I run ProcessMessages every loop, then it only will react every 5th second, so therefore the other loop that does the ProcessMessages be done at the same time as the loop. How can that be done? I've tried with timers (but they need ProcessMessages to respond), and I've tried with a seperate loop (but then it's stuck in the loop, and won't go to the filecopying). How would I get this work then?
0
Comment
Question by:chrml0606
[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
8 Comments
 
LVL 2

Assisted Solution

by:Tussin
Tussin earned 160 total points
ID: 9857126
You can use thread to solve this problem. Try looking at the borland demo code Demos\Threads\thrddemo.dpr
0
 
LVL 7

Expert Comment

by:sftweng
ID: 9857147
Run each as a separate thread. The following is taken from the Delphi help example for TThread in Help\Examples\PrgrsBar:

Objects

The example demonstrates using the TProgressBar and TThread objects.

Running

To run this example, load the project file from the Help\Examples\PrgrsBar directory.

Description

This example illustrates the use of a progress bar control, how to update the control, and how to manage threads during such a process.

unit Pg1;

interface

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

const
  WM_ThreadDoneMsg = WM_User + 8;

type
  TForm1 = class(TForm)
    ProgressBar1: TProgressBar;
    ProgressBar2: TProgressBar;
    Button1: TButton;
    Button2: TButton;
    TrackBar1: TTrackBar;
    TrackBar2: TTrackBar;
    Bevel1: TBevel;
    Bevel2: TBevel;
    Label1: TLabel;

    Label2: TLabel;
    Button3: TButton;
    Button4: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
    procedure TrackBar2Change(Sender: TObject);
    procedure FormDestroy(Sender: TObject);

  private
    { Private declarations }
    MyThread1 : TMyThread; // thread number 1
    MyThread2 : TMyThread; // thread number 2
    Thread1Active : boolean; // used to test if thread 1 is active
    Thread2Active : boolean; // used to test if thread 2 is active
    procedure ThreadDone(var AMessage : TMessage); message WM_ThreadDoneMsg; // Message to be sent back from thread when its done
  public
    { Public declarations }

  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject); // Create Thread 1
{ The thread will destroy iteself when it is done executing because FreeOnTerminate is set to true.
The first paramter is the priority, and the second is the progressbar to update.
}
begin
   if (MyThread1 = nil) or (Thread1Active = false) then // make sure its not already running

   begin
     MyThread1 := TMyThread.CreateIt(TrackBar1.Position, ProgressBar1);
     Thread1Active := true;
   end
   else
     ShowMessage('Thread still executing');
end;

procedure TForm1.Button2Click(Sender: TObject); // Create Thread 2
begin
   if (MyThread2 = nil) or (Thread2Active = false) then  // make sure its not already running
   begin
     MyThread2 := TMyThread.CreateIt(TrackBar2.Position, ProgressBar2);

     Thread2Active := true;
   end
   else
     ShowMessage('Thread still executing');
end;

procedure TForm1.Button3Click(Sender: TObject); // Terminate Thread 1
begin
  if (MyThread1 <> nil) and (Thread1Active = true) then  // check to see if it is running
    MyThread1.Terminate
  else
   ShowMessage('Thread not started');
end;

procedure TForm1.Button4Click(Sender: TObject); // Terminate Thread 2

begin
  if (MyThread2 <> nil) and (Thread2Active = true) then  // check to see if it is running
    MyThread2.Terminate
  else
    ShowMessage('Thread not started');
end;

procedure TForm1.ThreadDone(var AMessage: TMessage); // keep track of when and which thread is done executing
begin
  if ((MyThread1 <> nil) and (MyThread1.ThreadID = cardinal(AMessage.WParam))) then

  begin
      Thread1Active := false;
  end;
  if ((MyThread2 <> nil) and (MyThread2.ThreadID = cardinal(AMessage.WParam))) then
  begin
      Thread2Active := false;
  end;
end;


procedure TForm1.FormCreate(Sender: TObject); // initialize to zero
begin
  Thread1Active := false;
  Thread2Active := false;
end;


procedure TForm1.TrackBar1Change(Sender: TObject); // set Thread 1 Priority

begin
  if (MyThread1 <> nil) and (Thread1Active = true) then
     MyThread1.priority := TThreadPriority(TrackBar1.Position);
end;

procedure TForm1.TrackBar2Change(Sender: TObject); // set Thread 2 Priority
begin
  if (MyThread2 <> nil) and (Thread2Active = true) then
    MyThread2.priority := TThreadPriority(TrackBar2.Position);
end;


procedure TForm1.FormDestroy(Sender: TObject); // Terminate any threads still running

begin
   if (MyThread1 <> nil) and (Thread1Active = true) then
   begin
     MyThread1.Terminate;
     MyThread1.WaitFor;  // wait for it to terminate
   end;
   if (MyThread2 <> nil) and (Thread2Active = true) then
   begin
     MyThread2.Terminate;
     MyThread2.WaitFor;
   end;
end;

end.
0
 

Author Comment

by:chrml0606
ID: 9857209
Ah, ok, I see, but where is the procedure that the thread is doing? I mean, if I was going to do some filecopying here, then where would I have the filecopying code?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 7

Expert Comment

by:sftweng
ID: 9857234
The ThrdDemo sample makes it a little more obvious:

procedure TThreadSortForm.BubbleSortBoxPaint(Sender: TObject);
begin
  PaintArray(BubbleSortBox, BubbleSortArray);
end;

procedure TThreadSortForm.SelectionSortBoxPaint(Sender: TObject);
begin
  PaintArray(SelectionSortBox, SelectionSortArray);
end;

procedure TThreadSortForm.QuickSortBoxPaint(Sender: TObject);
begin
  PaintArray(QuickSortBox, QuickSortArray);
end;

procedure TThreadSortForm.FormCreate(Sender: TObject);
begin
  RandomizeArrays;
end;

procedure TThreadSortForm.StartBtnClick(Sender: TObject);
begin
  RandomizeArrays;
  ThreadsRunning := 3;
  with TBubbleSort.Create(BubbleSortBox, BubbleSortArray) do
    OnTerminate := ThreadDone;
  with TSelectionSort.Create(SelectionSortBox, SelectionSortArray) do
    OnTerminate := ThreadDone;
  with TQuickSort.Create(QuickSortBox, QuickSortArray) do
    OnTerminate := ThreadDone;
  StartBtn.Enabled := False;
end;
0
 
LVL 7

Accepted Solution

by:
sftweng earned 840 total points
ID: 9857244
To create and use a new thread object:

Choose File | New | Other | Thread Object to create a new unit that contains an object derived from the TThread class.
      Define the thread object’s Execute method by inserting the code that should execute when the thread is executed.
0
 

Author Comment

by:chrml0606
ID: 9857292
Thanks for help :)! Accepted your answer, and gave the other dude 40 points for showing interest :)!
0
 
LVL 1

Expert Comment

by:sahilkhan20
ID: 9857310
chrml0606 :

you will have to override the Execute Method and place your code in there.

Sahil
0
 

Author Comment

by:chrml0606
ID: 9857317
Yup, I know :D! I got it working thanks to sftweng.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

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…
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…
In this video we outline the Physical Segments view of NetCrunch network monitor. By following this brief how-to video, you will be able to learn how NetCrunch visualizes your network, how granular is the information collected, as well as where to f…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
Suggested Courses

770 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