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.
Sixth Day • Nineth Day
Please e-mail me with any comments!
© 27.12.96 Sebastian Boßung
• Home