Digging deeper in Delphi

Threads are parts of a program that can be executed “simultaniously”. The are assigned running time by the operating system. Usually a Delphi project has just one thread (it is created without you knowing about it). This is the main thread. When it is terminated the whole program quits. Threads are useful if you want to perform time consuming tasks in the background, while the user can go on using your program. This was somewhat hard to achieve in 16-bit Windows. 32-bit Windows now provides threads which free the programmer of the co-ordiantion overhead. I will not create a sample project for threads but just discuss the one that comes with Delphi. You can find it in the Delphi 3\Demos\Thread directory. Load it a run it to see what it does.

Now take a look at the source, especially the SortThds unit. In the type block you will find class called TSortThread. It inherits from TThread which is a class provided with Delphi. It encapsulates the Windows Thread object, so you don’t need to make Windows function calls.

TSortThread = class(TThread)
private
FBox: TPaintBox;
FSortArray: PSortArray;
FSize: Integer;
FA, FB, FI, FJ: Integer;
procedure DoVisualSwap;
protected
procedure Execute; override;
procedure VisualSwap(A, B, I, J: Integer);
procedure Sort(var A: array of Integer); virtual; abstract;
public
constructor Create(Box: TPaintBox; var SortArray: array of Integer);
end;

The most important method is the execute procedure. It is called when the thread starts and performs the calculations (or calls the functions that perform the calculations). Further down are more thread classed which define the type of sorting to be done. These are the ones that are used by the program. The purpose of TSortThread is to provide common functionality to all the different sorting-threads.

If you have more than one thread running (this is always the case when you create a thread yourself), there is danger that both threads want to access data simultaniously. This would result in a collision with unpredictable results. To avoid this the TThread class a a method called synchronize. It synchronizes the activities of the threads. It is passed a procedure as a parameter that is to be synchronized. In the example program VisualSwap has all the critical procedures in it. Thus the threads call
Synchronize(DoVisualSwap);

to synchronize. The parameters for VisualSwap are contained in the object because you cannot pass Synchronize a procedure with parameters.

Now take a look at the other unit: ThSort. The StartBtnClick procedure initializes the Threads:

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;

You do not have to do it the way it is done here. You could also use:

//…
var
MyThread: TBubbleSort;
//…
begin
MyThread:= TBubbleSort.Create(BubbleSortBox, BubbleSortArray);
MyThread.OnTerminate:= ThreadDone;
//…

This is only useful if you need the pointer to the thread later on. You need this pointer to change the priority of the Thread in the course of the program. Each thread has a priority property that you can set to six values (taken from the help file):

TThreadPriority = (tpIdle, tpLowest, tpLower, tpNormal, tpHigher,
tpHighest, tpTimeCritical);

You can change it whenever you like.
Using DLLs

Note: This is just a very basic introduction. If you need more details please refer to the Dephi help system. There is a good series of articles on it.

A DLL is – like an executable – a compiled program module. However, it cannot be run by itself but rather is a collection of functions that are called by outside programs. The abbriviation DLL stands for Dynamic Link Library. It is not compiled into the EXE-file at compile-time but linked into it at run-time.

Because DLLs are independend of the programming language you use (well, almost) there are a couple of things you should be aware of:
To call a DLL function the calling program has to know the name of the function. This is a problem with some C++ compilers who add type information to the function’s name.
The types of the parameters have to be identical (or at least compatible) in both languages. If you want to call a DLL function that uses the C type int as a Parameter, you have to make it an integer in your Pascal program.
The calling program and the DLL have to use the same calling conventions. This means that the parameters have to be passed in the same order.
Importing functions – a simple example

There is a Windows DLL called USER32.DLL which includes the function MessageBox. To use this function in your program you have to tell the compiler to import it from the DLL:

function MessageBox(HWnd: Integer; Text, Caption: PChar;
Flags: Integer): Integer; stdcall;
external ‘user32.dll’ name ‘MessageBoxA’;

Open the file Win32.hlp in your Delphi\Help director and take a look at the description of the function. You will see how the parameters are matched by Delphi types. The word “stdcall” after the normal declaration of the function causes the compiler to use C calling conventions. “external” tells the compiler not to look for the function in a unit but rather the specified outside file (a DLL in this case). After external you pass the name of the DLL. Please note that it has to be in the current, \Windows, or \Windows\System directory. If the name you use in Pacal is different form the name of the function in the DLL you have to specify the real name of the function. Please be aware that C is case sensitive and that your function name in Pascal has to be in the correct case if you don’t use the name directive.
Writing DLLs in Delphi

Writing your own DLLs in Delphi is very easy. There are only a few things you have to consider, which will probably become clear in this example:

library Test;

uses
MyUnit;

exports
MyFunction name ‘MyFunction’;

begin
end.

Of course this only works if MyFunction is declared in MyUnit.

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5 out of 5)
Loading ... Loading ...

Related Articles

Random Articles

Post a Comment