Introduction:
In this tutorial I'll be showing you how to use the TTimer object to run multiple functions or procedures at once. This is called Multithreading.
It's very usefull when you want to create your progress report all the time the script is running, or when you just want to scan for a certain event, while a script is running.
It's not "real" multithreading though. Because real MT typically enables you to safe Critical Sections, synchronize threads or vary the priority of a thread...
Example Script (no timers):
We are wanting to use an extra thread for our proggy in this script. We also want another thread, to do stuff, like "painting" a progress report or such.
All of that will happen while our actuall script is looping the woodcutting procedures.
SCAR Code:
program Timers;
var
loadcount : integer;
procedure proggy;
begin
ClearReport;
AddToReport('Scriptname');
AddToReport('Time Running: '+IntToStr(GetTimeRunning));
AddToReport('Loads: '+IntToStr(loadcount));
end;
procedure Woodcutting;
begin
WriteLn('Woodcutting');
wait(5000);
end;
procedure Dropping;
begin
WriteLn('Dropping');
wait(5000);
end;
procedure mainloop;
begin
Woodcutting;
Dropping;
inc(loadcount);
end;
begin
repeat
mainloop;
proggy;
until(loadcount=10);
end.
Generating a Timer and calling it:
We will generate a new form(not visible) and Create a new timer on that form. We may also apply our timer to the undetermined nil pointer, which would spare us the form, but may result in exceptions when not freed correctly.
I hope i commented everything suffieciently. If you still got any question don't bother to ask .
Code with timers/Multithreading:
SCAR Code:
program Timers;
var
//Timer and Form Vars
frmDesign: TForm;
thread1, thread2: TTimer;
//proggy var
loadcount : integer;
procedure proggy;
begin
ClearReport;
AddToReport('Scriptname');
AddToReport('Time Running: '+IntToStr(GetTimeRunning));
AddToReport('Loads: '+IntToStr(loadcount));
end;
//The procedure of our first thread/timer
procedure t1(sender: TObject);
begin
proggy;
end;
//The procedure of our second thread/timer
procedure t2(sender: TObject);
begin
writeln('Timer 2 Looping, painting the progress report and such');
end;
//Creating the Form
procedure InitForm;
begin
frmDesign := CreateForm;
end;
//Creating the Timer
procedure InitTimer;
begin
thread1 := TTimer.Create(frmDesign);
thread2 := TTimer.Create(frmDesign);
end;
procedure SafeInitFormandTimer;
var
v: TVariantArray;
begin
setarraylength(v, 0);
ThreadSafeCall('InitForm',v);
ThreadSafeCall('InitTimer',v);
//Function which is run everytime the timer loops
thread1.OnTimer := @t1;
//timer interval in ms
thread1.Interval := 300;
//enabled
thread1.enabled := TRUE;
//Same as above for the second timer/thread
thread2.OnTimer := @t2;
thread2.Interval := 200;
thread2.enabled := TRUE;
end;
procedure Woodcutting;
begin
WriteLn('Woodcutting');
wait(5000);
end;
procedure Dropping;
begin
WriteLn('Dropping');
wait(5000);
end;
procedure mainloop;
begin
Woodcutting;
Dropping;
inc(loadcount);
end;
begin
//Generating and setting up the timer
SafeInitFormandTimer;
repeat
mainloop;
// proggy;
until(loadcount = 10);
// And Freeing the memory
FreeForm(frmDesign);
end.
Conclusion:
So, this technique can be used whenever you need multiple tasks done at the "same time". Watch out that you do not write in the same var or use a function multiple times at the same time, that may cause access violations and stops the script.
Another good thing, where a thread/timer comes in handy is, when you want your script to download a website, but you do not want the whole script to stop and wait till it's done. Or when you want to download multiple websites at once .
If anything is unclear, feel free to ask .
~caused