mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-05 17:39:36 +01:00
added multithreading examples
git-svn-id: trunk@9575 -
This commit is contained in:
parent
41947d6c28
commit
f10441b47f
15
.gitattributes
vendored
15
.gitattributes
vendored
@ -994,11 +994,26 @@ examples/memotest.lpi svneol=native#text/plain
|
|||||||
examples/memotest.pp svneol=native#text/pascal
|
examples/memotest.pp svneol=native#text/pascal
|
||||||
examples/messagedialogs.lpi svneol=native#text/plain
|
examples/messagedialogs.lpi svneol=native#text/plain
|
||||||
examples/messagedialogs.pp svneol=native#text/pascal
|
examples/messagedialogs.pp svneol=native#text/pascal
|
||||||
|
examples/multithreading/criticalsectionexample1.lpi svneol=native#text/plain
|
||||||
|
examples/multithreading/criticalsectionexample1.lpr svneol=native#text/plain
|
||||||
|
examples/multithreading/criticalsectionunit1.lfm svneol=native#text/plain
|
||||||
|
examples/multithreading/criticalsectionunit1.lrs svneol=native#text/plain
|
||||||
|
examples/multithreading/criticalsectionunit1.pas svneol=native#text/plain
|
||||||
examples/multithreading/mainunit.lfm svneol=native#text/plain
|
examples/multithreading/mainunit.lfm svneol=native#text/plain
|
||||||
examples/multithreading/mainunit.lrs svneol=native#text/plain
|
examples/multithreading/mainunit.lrs svneol=native#text/plain
|
||||||
examples/multithreading/mainunit.pas svneol=native#text/plain
|
examples/multithreading/mainunit.pas svneol=native#text/plain
|
||||||
examples/multithreading/multithreadingexample1.lpi svneol=native#text/plain
|
examples/multithreading/multithreadingexample1.lpi svneol=native#text/plain
|
||||||
examples/multithreading/multithreadingexample1.lpr svneol=native#text/plain
|
examples/multithreading/multithreadingexample1.lpr svneol=native#text/plain
|
||||||
|
examples/multithreading/processmessagesunit1.lfm svneol=native#text/plain
|
||||||
|
examples/multithreading/processmessagesunit1.lrs svneol=native#text/plain
|
||||||
|
examples/multithreading/processmessagesunit1.pas svneol=native#text/plain
|
||||||
|
examples/multithreading/singlethreadingexample1.lpi svneol=native#text/plain
|
||||||
|
examples/multithreading/singlethreadingexample1.lpr svneol=native#text/plain
|
||||||
|
examples/multithreading/waitforexample1.lpi svneol=native#text/plain
|
||||||
|
examples/multithreading/waitforexample1.lpr svneol=native#text/plain
|
||||||
|
examples/multithreading/waitforunit1.lfm svneol=native#text/plain
|
||||||
|
examples/multithreading/waitforunit1.lrs svneol=native#text/plain
|
||||||
|
examples/multithreading/waitforunit1.pas svneol=native#text/plain
|
||||||
examples/notebk.lpi svneol=native#text/plain
|
examples/notebk.lpi svneol=native#text/plain
|
||||||
examples/notebk.pp svneol=native#text/pascal
|
examples/notebk.pp svneol=native#text/pascal
|
||||||
examples/notebku.pp svneol=native#text/pascal
|
examples/notebku.pp svneol=native#text/pascal
|
||||||
|
|||||||
62
examples/multithreading/criticalsectionexample1.lpi
Normal file
62
examples/multithreading/criticalsectionexample1.lpi
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<CONFIG>
|
||||||
|
<ProjectOptions>
|
||||||
|
<PathDelim Value="/"/>
|
||||||
|
<Version Value="5"/>
|
||||||
|
<General>
|
||||||
|
<SessionStorage Value="InProjectDir"/>
|
||||||
|
<MainUnit Value="0"/>
|
||||||
|
<TargetFileExt Value=""/>
|
||||||
|
</General>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
<IgnoreBinaries Value="False"/>
|
||||||
|
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||||
|
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||||
|
</PublishOptions>
|
||||||
|
<RunParams>
|
||||||
|
<local>
|
||||||
|
<FormatVersion Value="1"/>
|
||||||
|
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||||
|
</local>
|
||||||
|
</RunParams>
|
||||||
|
<RequiredPackages Count="1">
|
||||||
|
<Item1>
|
||||||
|
<PackageName Value="LCL"/>
|
||||||
|
</Item1>
|
||||||
|
</RequiredPackages>
|
||||||
|
<Units Count="2">
|
||||||
|
<Unit0>
|
||||||
|
<Filename Value="criticalsectionexample1.lpr"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="CriticalSectionExample1"/>
|
||||||
|
</Unit0>
|
||||||
|
<Unit1>
|
||||||
|
<Filename Value="criticalsectionunit1.pas"/>
|
||||||
|
<ComponentName Value="Form1"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<ResourceFilename Value="criticalsectionunit1.lrs"/>
|
||||||
|
<UnitName Value="CriticalSectionUnit1"/>
|
||||||
|
</Unit1>
|
||||||
|
</Units>
|
||||||
|
</ProjectOptions>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="5"/>
|
||||||
|
<SearchPaths>
|
||||||
|
<SrcPath Value="$(LazarusDir)/lcl/;$(LazarusDir)/lcl/interfaces/$(LCLWidgetType)/"/>
|
||||||
|
</SearchPaths>
|
||||||
|
<CodeGeneration>
|
||||||
|
<Generate Value="Faster"/>
|
||||||
|
</CodeGeneration>
|
||||||
|
<Linking>
|
||||||
|
<Options>
|
||||||
|
<Win32>
|
||||||
|
<GraphicApplication Value="True"/>
|
||||||
|
</Win32>
|
||||||
|
</Options>
|
||||||
|
</Linking>
|
||||||
|
<Other>
|
||||||
|
<CompilerPath Value="$(CompPath)"/>
|
||||||
|
</Other>
|
||||||
|
</CompilerOptions>
|
||||||
|
</CONFIG>
|
||||||
18
examples/multithreading/criticalsectionexample1.lpr
Normal file
18
examples/multithreading/criticalsectionexample1.lpr
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
program CriticalSectionExample1;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
uses
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
cthreads,
|
||||||
|
{$ENDIF}
|
||||||
|
Interfaces, // this includes the LCL widgetset
|
||||||
|
Forms
|
||||||
|
{ add your units here }, CriticalSectionUnit1;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Application.Initialize;
|
||||||
|
Application.CreateForm(TForm1, Form1);
|
||||||
|
Application.Run;
|
||||||
|
end.
|
||||||
|
|
||||||
43
examples/multithreading/criticalsectionunit1.lfm
Normal file
43
examples/multithreading/criticalsectionunit1.lfm
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
object Form1: TForm1
|
||||||
|
Caption = 'Form1'
|
||||||
|
ClientHeight = 169
|
||||||
|
ClientWidth = 312
|
||||||
|
PixelsPerInch = 75
|
||||||
|
HorzScrollBar.Page = 311
|
||||||
|
VertScrollBar.Page = 168
|
||||||
|
Left = 286
|
||||||
|
Height = 169
|
||||||
|
Top = 202
|
||||||
|
Width = 312
|
||||||
|
object Label1: TLabel
|
||||||
|
Caption = 'Label1'
|
||||||
|
Color = clNone
|
||||||
|
ParentColor = False
|
||||||
|
Left = 43
|
||||||
|
Height = 17
|
||||||
|
Top = 125
|
||||||
|
Width = 65
|
||||||
|
end
|
||||||
|
object CountWithCritSecButton: TButton
|
||||||
|
AutoSize = True
|
||||||
|
BorderSpacing.InnerBorder = 4
|
||||||
|
Caption = 'Count with critical section'
|
||||||
|
OnClick = CountWithCritSecButtonClick
|
||||||
|
TabOrder = 0
|
||||||
|
Left = 40
|
||||||
|
Height = 26
|
||||||
|
Top = 24
|
||||||
|
Width = 158
|
||||||
|
end
|
||||||
|
object CountWithoutCritSecButton: TButton
|
||||||
|
AutoSize = True
|
||||||
|
BorderSpacing.InnerBorder = 4
|
||||||
|
Caption = 'Count without critical section'
|
||||||
|
OnClick = CountWithoutCritSecButtonClick
|
||||||
|
TabOrder = 1
|
||||||
|
Left = 40
|
||||||
|
Height = 26
|
||||||
|
Top = 64
|
||||||
|
Width = 175
|
||||||
|
end
|
||||||
|
end
|
||||||
16
examples/multithreading/criticalsectionunit1.lrs
Normal file
16
examples/multithreading/criticalsectionunit1.lrs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{ Dies ist eine automatisch erzeugte Lazarus-Ressourcendatei }
|
||||||
|
|
||||||
|
LazarusResources.Add('TForm1','FORMDATA',[
|
||||||
|
'TPF0'#6'TForm1'#5'Form1'#7'Caption'#6#5'Form1'#12'ClientHeight'#3#169#0#11'C'
|
||||||
|
+'lientWidth'#3'8'#1#13'PixelsPerInch'#2'K'#18'HorzScrollBar.Page'#3'7'#1#18
|
||||||
|
+'VertScrollBar.Page'#3#168#0#4'Left'#3#30#1#6'Height'#3#169#0#3'Top'#3#202#0
|
||||||
|
+#5'Width'#3'8'#1#0#6'TLabel'#6'Label1'#7'Caption'#6#6'Label1'#5'Color'#7#6'c'
|
||||||
|
+'lNone'#11'ParentColor'#8#4'Left'#2'+'#6'Height'#2#17#3'Top'#2'}'#5'Width'#2
|
||||||
|
+'A'#0#0#7'TButton'#22'CountWithCritSecButton'#8'AutoSize'#9#25'BorderSpacing'
|
||||||
|
+'.InnerBorder'#2#4#7'Caption'#6#27'Count with critical section'#7'OnClick'#7
|
||||||
|
+#27'CountWithCritSecButtonClick'#8'TabOrder'#2#0#4'Left'#2'('#6'Height'#2#26
|
||||||
|
+#3'Top'#2#24#5'Width'#3#158#0#0#0#7'TButton'#25'CountWithoutCritSecButton'#8
|
||||||
|
+'AutoSize'#9#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6#30'Count without'
|
||||||
|
+' critical section'#7'OnClick'#7#30'CountWithoutCritSecButtonClick'#8'TabOrd'
|
||||||
|
+'er'#2#1#4'Left'#2'('#6'Height'#2#26#3'Top'#2'@'#5'Width'#3#175#0#0#0#0
|
||||||
|
]);
|
||||||
147
examples/multithreading/criticalsectionunit1.pas
Normal file
147
examples/multithreading/criticalsectionunit1.pas
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
{
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This source is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This code is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* A copy of the GNU General Public License is available on the World *
|
||||||
|
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||||
|
* obtain it by writing to the Free Software Foundation, *
|
||||||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
Demo to show how 5 threads increases a counter.
|
||||||
|
With and without critical sections.
|
||||||
|
|
||||||
|
With critical sections you will always get 50000.
|
||||||
|
Without you will see different results on each run and depending on your
|
||||||
|
system.
|
||||||
|
}
|
||||||
|
unit CriticalSectionUnit1;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, Buttons,
|
||||||
|
StdCtrls, LCLProc, LCLType, LCLIntf;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TMyThread }
|
||||||
|
|
||||||
|
TMyThread = class(TThread)
|
||||||
|
public
|
||||||
|
procedure Execute; override;
|
||||||
|
property Finished: boolean read FFinished write FFinished;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TForm1 }
|
||||||
|
|
||||||
|
TForm1 = class(TForm)
|
||||||
|
CountWithoutCritSecButton: TButton;
|
||||||
|
CountWithCritSecButton: TButton;
|
||||||
|
Label1: TLabel;
|
||||||
|
procedure CountWithCritSecButtonClick(Sender: TObject);
|
||||||
|
procedure CountWithoutCritSecButtonClick(Sender: TObject);
|
||||||
|
private
|
||||||
|
public
|
||||||
|
CriticalSection: TCriticalSection;
|
||||||
|
Counter: integer;
|
||||||
|
UseCriticalSection: boolean;
|
||||||
|
procedure DoCounting;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
Form1: TForm1;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ TForm1 }
|
||||||
|
|
||||||
|
procedure TForm1.CountWithCritSecButtonClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
UseCriticalSection:=true;
|
||||||
|
DoCounting;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.CountWithoutCritSecButtonClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
UseCriticalSection:=false;
|
||||||
|
DoCounting;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.DoCounting;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
Threads: array[1..5] of TMyThread;
|
||||||
|
AllFinished: Boolean;
|
||||||
|
begin
|
||||||
|
Counter:=0;
|
||||||
|
|
||||||
|
// create the CriticalSection
|
||||||
|
InitializeCriticalSection(CriticalSection);
|
||||||
|
|
||||||
|
// start 5 threads
|
||||||
|
for i:=Low(Threads) to High(Threads) do
|
||||||
|
Threads[i]:=TMyThread.Create(false);
|
||||||
|
// wait till all threads finished
|
||||||
|
repeat
|
||||||
|
AllFinished:=true;
|
||||||
|
for i:=Low(Threads) to High(Threads) do
|
||||||
|
if not Threads[i].Finished then AllFinished:=false;
|
||||||
|
until AllFinished;
|
||||||
|
// free the threads
|
||||||
|
for i:=Low(Threads) to High(Threads) do
|
||||||
|
Threads[i].Free;
|
||||||
|
|
||||||
|
// free the CriticalSection
|
||||||
|
DeleteCriticalSection(CriticalSection);
|
||||||
|
|
||||||
|
// show the Counter
|
||||||
|
Label1.Caption:='Counter='+IntToStr(Counter);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TMyThread }
|
||||||
|
|
||||||
|
procedure TMyThread.Execute;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
CurCounter: LongInt;
|
||||||
|
j: Integer;
|
||||||
|
begin
|
||||||
|
// increment the counter many times
|
||||||
|
// Because the other threads are doing the same, it will frequently happen,
|
||||||
|
// that 2 (or more) threads read the same number, increment it by one and
|
||||||
|
// write the result back, overwriting the result of the other threads.
|
||||||
|
for i:=1 to 100000 do begin
|
||||||
|
if Form1.UseCriticalSection then
|
||||||
|
EnterCriticalSection(Form1.CriticalSection);
|
||||||
|
try
|
||||||
|
CurCounter:=Form1.Counter;
|
||||||
|
for j:=1 to 1000 do ;
|
||||||
|
inc(CurCounter);
|
||||||
|
Form1.Counter:=CurCounter;
|
||||||
|
finally
|
||||||
|
if Form1.UseCriticalSection then
|
||||||
|
LeaveCriticalSection(Form1.CriticalSection);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Finished:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
{$I criticalsectionunit1.lrs}
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
||||||
@ -17,6 +17,12 @@
|
|||||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
* *
|
* *
|
||||||
***************************************************************************
|
***************************************************************************
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
Demo to show, how to start a thread and how synchronize with the main
|
||||||
|
thread.
|
||||||
|
Important: The cthread unint must be added to the uses section of the .lpr
|
||||||
|
file. See multithreadingexample1.lpr.
|
||||||
}
|
}
|
||||||
unit MainUnit;
|
unit MainUnit;
|
||||||
|
|
||||||
@ -60,18 +66,21 @@ procedure TForm1.FormCreate(Sender: TObject);
|
|||||||
var
|
var
|
||||||
MyThread : TMyThread;
|
MyThread : TMyThread;
|
||||||
begin
|
begin
|
||||||
MyThread := TMyThread.Create(True); // This way it doesn't start automatically
|
MyThread := TMyThread.Create(True); // With the True parameter it doesn't start automatically
|
||||||
if Assigned(MyThread.FatalException) then
|
if Assigned(MyThread.FatalException) then
|
||||||
raise MyThread.FatalException;
|
raise MyThread.FatalException;
|
||||||
|
|
||||||
// Here the code initialises anything required before the threads starts executing
|
// Here the code initialises anything required before the threads starts executing
|
||||||
|
|
||||||
MyThread.Resume;
|
MyThread.Resume;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TMyThread }
|
{ TMyThread }
|
||||||
|
|
||||||
procedure TMyThread.ShowStatus;
|
procedure TMyThread.ShowStatus;
|
||||||
|
// this method is only called by Synchronize(@ShowStatus) and therefore
|
||||||
|
// executed by the main thread
|
||||||
|
// The main thread can access GUI elements, for example Form1.Caption.
|
||||||
begin
|
begin
|
||||||
Form1.Caption := fStatusText;
|
Form1.Caption := fStatusText;
|
||||||
end;
|
end;
|
||||||
@ -80,13 +89,13 @@ procedure TMyThread.Execute;
|
|||||||
var
|
var
|
||||||
newStatus : string;
|
newStatus : string;
|
||||||
begin
|
begin
|
||||||
fStatusText := 'Starting...';
|
fStatusText := 'TMyThread Starting...';
|
||||||
Synchronize(@Showstatus);
|
Synchronize(@Showstatus);
|
||||||
fStatusText := 'Running...';
|
fStatusText := 'TMyThread Running...';
|
||||||
while (not Terminated) and (true {any condition required}) do begin
|
while (not Terminated) and (true {any condition required}) do begin
|
||||||
|
|
||||||
//here goes the code of the main thread loop
|
//here goes the code of the main thread loop
|
||||||
newStatus:='Time: '+FormatDateTime('YYYY-MM-DD HH:NN:SS',Now);
|
newStatus:='TMyThread Time: '+FormatDateTime('YYYY-MM-DD HH:NN:SS',Now);
|
||||||
|
|
||||||
if NewStatus <> fStatusText then begin
|
if NewStatus <> fStatusText then begin
|
||||||
fStatusText := newStatus;
|
fStatusText := newStatus;
|
||||||
|
|||||||
@ -6,12 +6,11 @@
|
|||||||
<General>
|
<General>
|
||||||
<SessionStorage Value="InProjectDir"/>
|
<SessionStorage Value="InProjectDir"/>
|
||||||
<MainUnit Value="0"/>
|
<MainUnit Value="0"/>
|
||||||
|
<IconPath Value="./"/>
|
||||||
<TargetFileExt Value=""/>
|
<TargetFileExt Value=""/>
|
||||||
</General>
|
</General>
|
||||||
<LazDoc Paths=""/>
|
|
||||||
<PublishOptions>
|
<PublishOptions>
|
||||||
<Version Value="2"/>
|
<Version Value="2"/>
|
||||||
<IgnoreBinaries Value="False"/>
|
|
||||||
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||||
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||||
</PublishOptions>
|
</PublishOptions>
|
||||||
|
|||||||
@ -3,12 +3,13 @@ program MultiThreadingExample1;
|
|||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
|
// for multi threading the cthreads unit must be used on unix systems:
|
||||||
|
// for example: Linux, MacOSX, FreeBSD, Solaris
|
||||||
{$IFDEF UNIX}
|
{$IFDEF UNIX}
|
||||||
cthreads,
|
cthreads,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
Interfaces, // this includes the LCL widgetset
|
Interfaces, // this includes the LCL widgetset
|
||||||
Forms
|
Forms, MainUnit;
|
||||||
{ add your units here }, MainUnit;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Application.Initialize;
|
Application.Initialize;
|
||||||
|
|||||||
34
examples/multithreading/processmessagesunit1.lfm
Normal file
34
examples/multithreading/processmessagesunit1.lfm
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
object Form1: TForm1
|
||||||
|
Caption = 'Form1'
|
||||||
|
ClientHeight = 142
|
||||||
|
ClientWidth = 303
|
||||||
|
OnCreate = FormCreate
|
||||||
|
PixelsPerInch = 75
|
||||||
|
HorzScrollBar.Page = 302
|
||||||
|
VertScrollBar.Page = 141
|
||||||
|
Left = 286
|
||||||
|
Height = 142
|
||||||
|
Top = 202
|
||||||
|
Width = 303
|
||||||
|
object StartStopButton: TButton
|
||||||
|
Anchors = [akTop]
|
||||||
|
BorderSpacing.InnerBorder = 4
|
||||||
|
Caption = 'Start'
|
||||||
|
OnClick = StartStopButtonClick
|
||||||
|
TabOrder = 0
|
||||||
|
Left = 72
|
||||||
|
Height = 25
|
||||||
|
Top = 40
|
||||||
|
Width = 158
|
||||||
|
end
|
||||||
|
object ProgressBar1: TProgressBar
|
||||||
|
Anchors = [akTop, akLeft, akRight]
|
||||||
|
Max = 1000
|
||||||
|
Smooth = True
|
||||||
|
Step = 1
|
||||||
|
Left = 32
|
||||||
|
Height = 20
|
||||||
|
Top = 88
|
||||||
|
Width = 244
|
||||||
|
end
|
||||||
|
end
|
||||||
14
examples/multithreading/processmessagesunit1.lrs
Normal file
14
examples/multithreading/processmessagesunit1.lrs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{ Dies ist eine automatisch erzeugte Lazarus-Ressourcendatei }
|
||||||
|
|
||||||
|
LazarusResources.Add('TForm1','FORMDATA',[
|
||||||
|
'TPF0'#6'TForm1'#5'Form1'#7'Caption'#6#5'Form1'#12'ClientHeight'#3#142#0#11'C'
|
||||||
|
+'lientWidth'#3'/'#1#8'OnCreate'#7#10'FormCreate'#13'PixelsPerInch'#2'K'#18'H'
|
||||||
|
+'orzScrollBar.Page'#3'.'#1#18'VertScrollBar.Page'#3#141#0#4'Left'#3#30#1#6'H'
|
||||||
|
+'eight'#3#142#0#3'Top'#3#202#0#5'Width'#3'/'#1#0#7'TButton'#15'StartStopButt'
|
||||||
|
+'on'#7'Anchors'#11#5'akTop'#0#25'BorderSpacing.InnerBorder'#2#4#7'Caption'#6
|
||||||
|
+#5'Start'#7'OnClick'#7#20'StartStopButtonClick'#8'TabOrder'#2#0#4'Left'#2'H'
|
||||||
|
+#6'Height'#2#25#3'Top'#2'('#5'Width'#3#158#0#0#0#12'TProgressBar'#12'Progres'
|
||||||
|
+'sBar1'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#3'Max'#3#232#3#6'Smoot'
|
||||||
|
+'h'#9#4'Step'#2#1#4'Left'#2' '#6'Height'#2#20#3'Top'#2'X'#5'Width'#3#244#0#0
|
||||||
|
+#0#0
|
||||||
|
]);
|
||||||
138
examples/multithreading/processmessagesunit1.pas
Normal file
138
examples/multithreading/processmessagesunit1.pas
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
{
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This source is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This code is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* A copy of the GNU General Public License is available on the World *
|
||||||
|
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||||
|
* obtain it by writing to the Free Software Foundation, *
|
||||||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
Demo to show, how to process a big file with the main thread.
|
||||||
|
}
|
||||||
|
unit ProcessMessagesUnit1;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, Buttons,
|
||||||
|
ComCtrls;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TForm1 }
|
||||||
|
|
||||||
|
TForm1 = class(TForm)
|
||||||
|
ProgressBar1: TProgressBar;
|
||||||
|
StartStopButton: TButton;
|
||||||
|
procedure FormCreate(Sender: TObject);
|
||||||
|
procedure StartStopButtonClick(Sender: TObject);
|
||||||
|
private
|
||||||
|
procedure Run;
|
||||||
|
procedure UpdateButton;
|
||||||
|
public
|
||||||
|
Running: boolean;
|
||||||
|
Aborting: boolean;
|
||||||
|
Filename: String;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
Form1: TForm1;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ TForm1 }
|
||||||
|
|
||||||
|
procedure TForm1.FormCreate(Sender: TObject);
|
||||||
|
begin
|
||||||
|
Filename:='processmessagesunit1.pas';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.StartStopButtonClick(Sender: TObject);
|
||||||
|
begin
|
||||||
|
if not Running then
|
||||||
|
Run
|
||||||
|
else
|
||||||
|
Aborting:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.Run;
|
||||||
|
var
|
||||||
|
fs: TFileStream;
|
||||||
|
Buffer: string;
|
||||||
|
Count: LongInt;
|
||||||
|
i: Integer;
|
||||||
|
Last: TDateTime;
|
||||||
|
begin
|
||||||
|
if Running then exit;
|
||||||
|
Running:=true;
|
||||||
|
UpdateButton;
|
||||||
|
try
|
||||||
|
// open a file
|
||||||
|
fs:=TFileStream.Create(Filename,fmOpenRead);
|
||||||
|
try
|
||||||
|
SetLength(Buffer,10);
|
||||||
|
while true do begin
|
||||||
|
|
||||||
|
// process all user events, like clicking on the button
|
||||||
|
Application.ProcessMessages;
|
||||||
|
if Aborting or Application.Terminated then break;
|
||||||
|
|
||||||
|
// read some bytes
|
||||||
|
Count:=fs.Read(Buffer[1],length(Buffer));
|
||||||
|
if Count=0 then break;
|
||||||
|
|
||||||
|
// process ...
|
||||||
|
for i:=1 to Count do begin
|
||||||
|
Last:=Now;
|
||||||
|
repeat
|
||||||
|
until Now-Last>(double(1)/fs.Size)/10000;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// show progress
|
||||||
|
ProgressBar1.Position:=ProgressBar1.Min
|
||||||
|
+((ProgressBar1.Max-ProgressBar1.Min+1)*fs.Position) div fs.Size;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
fs.Free;
|
||||||
|
end;
|
||||||
|
except
|
||||||
|
on E: Exception do begin
|
||||||
|
MessageDlg('Error',E.Message,mtError,[mbCancel],0);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Aborting:=false;
|
||||||
|
Running:=false;
|
||||||
|
UpdateButton;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.UpdateButton;
|
||||||
|
begin
|
||||||
|
if Running then begin
|
||||||
|
if Aborting then
|
||||||
|
StartStopButton.Caption:='Aborting ...'
|
||||||
|
else
|
||||||
|
StartStopButton.Caption:='Running ...';
|
||||||
|
end else begin
|
||||||
|
StartStopButton.Caption:='Start';
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
{$I processmessagesunit1.lrs}
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
||||||
63
examples/multithreading/singlethreadingexample1.lpi
Normal file
63
examples/multithreading/singlethreadingexample1.lpi
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<CONFIG>
|
||||||
|
<ProjectOptions>
|
||||||
|
<PathDelim Value="/"/>
|
||||||
|
<Version Value="5"/>
|
||||||
|
<General>
|
||||||
|
<SessionStorage Value="InProjectDir"/>
|
||||||
|
<MainUnit Value="0"/>
|
||||||
|
<IconPath Value="./"/>
|
||||||
|
<TargetFileExt Value=""/>
|
||||||
|
</General>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
<IgnoreBinaries Value="False"/>
|
||||||
|
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||||
|
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||||
|
</PublishOptions>
|
||||||
|
<RunParams>
|
||||||
|
<local>
|
||||||
|
<FormatVersion Value="1"/>
|
||||||
|
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||||
|
</local>
|
||||||
|
</RunParams>
|
||||||
|
<RequiredPackages Count="1">
|
||||||
|
<Item1>
|
||||||
|
<PackageName Value="LCL"/>
|
||||||
|
</Item1>
|
||||||
|
</RequiredPackages>
|
||||||
|
<Units Count="2">
|
||||||
|
<Unit0>
|
||||||
|
<Filename Value="singlethreadingexample1.lpr"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="SingleThreadingExample1"/>
|
||||||
|
</Unit0>
|
||||||
|
<Unit1>
|
||||||
|
<Filename Value="processmessagesunit1.pas"/>
|
||||||
|
<ComponentName Value="Form1"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<ResourceFilename Value="processmessagesunit1.lrs"/>
|
||||||
|
<UnitName Value="ProcessMessagesUnit1"/>
|
||||||
|
</Unit1>
|
||||||
|
</Units>
|
||||||
|
</ProjectOptions>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="5"/>
|
||||||
|
<SearchPaths>
|
||||||
|
<SrcPath Value="$(LazarusDir)/lcl/;$(LazarusDir)/lcl/interfaces/$(LCLWidgetType)/"/>
|
||||||
|
</SearchPaths>
|
||||||
|
<CodeGeneration>
|
||||||
|
<Generate Value="Faster"/>
|
||||||
|
</CodeGeneration>
|
||||||
|
<Linking>
|
||||||
|
<Options>
|
||||||
|
<Win32>
|
||||||
|
<GraphicApplication Value="True"/>
|
||||||
|
</Win32>
|
||||||
|
</Options>
|
||||||
|
</Linking>
|
||||||
|
<Other>
|
||||||
|
<CompilerPath Value="$(CompPath)"/>
|
||||||
|
</Other>
|
||||||
|
</CompilerOptions>
|
||||||
|
</CONFIG>
|
||||||
18
examples/multithreading/singlethreadingexample1.lpr
Normal file
18
examples/multithreading/singlethreadingexample1.lpr
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
program SingleThreadingExample1;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
uses
|
||||||
|
{$IFDEF UNIX}{$IFDEF UseCThreads}
|
||||||
|
cthreads,
|
||||||
|
{$ENDIF}{$ENDIF}
|
||||||
|
Interfaces, // this includes the LCL widgetset
|
||||||
|
Forms
|
||||||
|
{ add your units here }, ProcessMessagesUnit1;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Application.Initialize;
|
||||||
|
Application.CreateForm(TForm1, Form1);
|
||||||
|
Application.Run;
|
||||||
|
end.
|
||||||
|
|
||||||
244
examples/multithreading/waitforexample1.lpi
Normal file
244
examples/multithreading/waitforexample1.lpi
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<CONFIG>
|
||||||
|
<ProjectOptions>
|
||||||
|
<PathDelim Value="/"/>
|
||||||
|
<Version Value="5"/>
|
||||||
|
<General>
|
||||||
|
<MainUnit Value="0"/>
|
||||||
|
<TargetFileExt Value=""/>
|
||||||
|
<ActiveEditorIndexAtStart Value="0"/>
|
||||||
|
</General>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
<IgnoreBinaries Value="False"/>
|
||||||
|
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||||
|
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||||
|
</PublishOptions>
|
||||||
|
<RunParams>
|
||||||
|
<local>
|
||||||
|
<FormatVersion Value="1"/>
|
||||||
|
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||||
|
</local>
|
||||||
|
</RunParams>
|
||||||
|
<RequiredPackages Count="1">
|
||||||
|
<Item1>
|
||||||
|
<PackageName Value="LCL"/>
|
||||||
|
</Item1>
|
||||||
|
</RequiredPackages>
|
||||||
|
<Units Count="8">
|
||||||
|
<Unit0>
|
||||||
|
<Filename Value="waitforexample1.lpr"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="WaitForExample1"/>
|
||||||
|
<CursorPos X="8" Y="14"/>
|
||||||
|
<TopLine Value="1"/>
|
||||||
|
<EditorIndex Value="1"/>
|
||||||
|
<UsageCount Value="20"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
</Unit0>
|
||||||
|
<Unit1>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<ComponentName Value="Form1"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<ResourceFilename Value="waitforunit1.lrs"/>
|
||||||
|
<UnitName Value="WaitForUnit1"/>
|
||||||
|
<CursorPos X="20" Y="32"/>
|
||||||
|
<TopLine Value="1"/>
|
||||||
|
<EditorIndex Value="0"/>
|
||||||
|
<UsageCount Value="20"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
</Unit1>
|
||||||
|
<Unit2>
|
||||||
|
<Filename Value="mainunit.pas"/>
|
||||||
|
<UnitName Value="MainUnit"/>
|
||||||
|
<CursorPos X="1" Y="27"/>
|
||||||
|
<TopLine Value="1"/>
|
||||||
|
<EditorIndex Value="7"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
</Unit2>
|
||||||
|
<Unit3>
|
||||||
|
<Filename Value="../../../freepascal/fpc/fcl/inc/custapp.pp"/>
|
||||||
|
<UnitName Value="CustApp"/>
|
||||||
|
<CursorPos X="14" Y="69"/>
|
||||||
|
<TopLine Value="47"/>
|
||||||
|
<EditorIndex Value="6"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
</Unit3>
|
||||||
|
<Unit4>
|
||||||
|
<Filename Value="../../../freepascal/fpc/rtl/objpas/classes/classesh.inc"/>
|
||||||
|
<CursorPos X="18" Y="1220"/>
|
||||||
|
<TopLine Value="1196"/>
|
||||||
|
<EditorIndex Value="3"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
</Unit4>
|
||||||
|
<Unit5>
|
||||||
|
<Filename Value="../../../freepascal/fpc/rtl/objpas/classes/classes.inc"/>
|
||||||
|
<CursorPos X="1" Y="103"/>
|
||||||
|
<TopLine Value="75"/>
|
||||||
|
<EditorIndex Value="5"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
</Unit5>
|
||||||
|
<Unit6>
|
||||||
|
<Filename Value="../../../freepascal/fpc/rtl/inc/threadh.inc"/>
|
||||||
|
<CursorPos X="59" Y="136"/>
|
||||||
|
<TopLine Value="110"/>
|
||||||
|
<EditorIndex Value="2"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
</Unit6>
|
||||||
|
<Unit7>
|
||||||
|
<Filename Value="../../../freepascal/fpc/rtl/linux/tthread.inc"/>
|
||||||
|
<CursorPos X="3" Y="292"/>
|
||||||
|
<TopLine Value="290"/>
|
||||||
|
<EditorIndex Value="4"/>
|
||||||
|
<UsageCount Value="10"/>
|
||||||
|
<Loaded Value="True"/>
|
||||||
|
</Unit7>
|
||||||
|
</Units>
|
||||||
|
<JumpHistory Count="30" HistoryIndex="29">
|
||||||
|
<Position1>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="158" Column="1" TopLine="122"/>
|
||||||
|
</Position1>
|
||||||
|
<Position2>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="112" Column="11" TopLine="90"/>
|
||||||
|
</Position2>
|
||||||
|
<Position3>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="102" Column="1" TopLine="90"/>
|
||||||
|
</Position3>
|
||||||
|
<Position4>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="145" Column="1" TopLine="109"/>
|
||||||
|
</Position4>
|
||||||
|
<Position5>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="45" Column="1" TopLine="45"/>
|
||||||
|
</Position5>
|
||||||
|
<Position6>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="145" Column="19" TopLine="109"/>
|
||||||
|
</Position6>
|
||||||
|
<Position7>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="72" Column="1" TopLine="50"/>
|
||||||
|
</Position7>
|
||||||
|
<Position8>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="144" Column="22" TopLine="108"/>
|
||||||
|
</Position8>
|
||||||
|
<Position9>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="110" Column="5" TopLine="56"/>
|
||||||
|
</Position9>
|
||||||
|
<Position10>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="105" Column="15" TopLine="102"/>
|
||||||
|
</Position10>
|
||||||
|
<Position11>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="76" Column="1" TopLine="54"/>
|
||||||
|
</Position11>
|
||||||
|
<Position12>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="114" Column="8" TopLine="96"/>
|
||||||
|
</Position12>
|
||||||
|
<Position13>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="115" Column="5" TopLine="93"/>
|
||||||
|
</Position13>
|
||||||
|
<Position14>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="53" Column="25" TopLine="26"/>
|
||||||
|
</Position14>
|
||||||
|
<Position15>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="45" Column="25" TopLine="23"/>
|
||||||
|
</Position15>
|
||||||
|
<Position16>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="118" Column="62" TopLine="96"/>
|
||||||
|
</Position16>
|
||||||
|
<Position17>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="133" Column="7" TopLine="111"/>
|
||||||
|
</Position17>
|
||||||
|
<Position18>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="40" Column="36" TopLine="18"/>
|
||||||
|
</Position18>
|
||||||
|
<Position19>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="66" Column="15" TopLine="35"/>
|
||||||
|
</Position19>
|
||||||
|
<Position20>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="133" Column="1" TopLine="101"/>
|
||||||
|
</Position20>
|
||||||
|
<Position21>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="21" Column="1" TopLine="1"/>
|
||||||
|
</Position21>
|
||||||
|
<Position22>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="149" Column="11" TopLine="116"/>
|
||||||
|
</Position22>
|
||||||
|
<Position23>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="71" Column="12" TopLine="49"/>
|
||||||
|
</Position23>
|
||||||
|
<Position24>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="103" Column="38" TopLine="81"/>
|
||||||
|
</Position24>
|
||||||
|
<Position25>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="102" Column="1" TopLine="81"/>
|
||||||
|
</Position25>
|
||||||
|
<Position26>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="148" Column="11" TopLine="115"/>
|
||||||
|
</Position26>
|
||||||
|
<Position27>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="129" Column="5" TopLine="114"/>
|
||||||
|
</Position27>
|
||||||
|
<Position28>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="150" Column="1" TopLine="114"/>
|
||||||
|
</Position28>
|
||||||
|
<Position29>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="147" Column="1" TopLine="116"/>
|
||||||
|
</Position29>
|
||||||
|
<Position30>
|
||||||
|
<Filename Value="waitforunit1.pas"/>
|
||||||
|
<Caret Line="152" Column="3" TopLine="118"/>
|
||||||
|
</Position30>
|
||||||
|
</JumpHistory>
|
||||||
|
</ProjectOptions>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="5"/>
|
||||||
|
<SearchPaths>
|
||||||
|
<SrcPath Value="$(LazarusDir)/lcl/;$(LazarusDir)/lcl/interfaces/$(LCLWidgetType)/"/>
|
||||||
|
</SearchPaths>
|
||||||
|
<CodeGeneration>
|
||||||
|
<Generate Value="Faster"/>
|
||||||
|
</CodeGeneration>
|
||||||
|
<Linking>
|
||||||
|
<Options>
|
||||||
|
<Win32>
|
||||||
|
<GraphicApplication Value="True"/>
|
||||||
|
</Win32>
|
||||||
|
</Options>
|
||||||
|
</Linking>
|
||||||
|
<Other>
|
||||||
|
<CompilerPath Value="$(CompPath)"/>
|
||||||
|
</Other>
|
||||||
|
</CompilerOptions>
|
||||||
|
</CONFIG>
|
||||||
18
examples/multithreading/waitforexample1.lpr
Normal file
18
examples/multithreading/waitforexample1.lpr
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
program WaitForExample1;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
uses
|
||||||
|
{$IFDEF UNIX}
|
||||||
|
cthreads,
|
||||||
|
{$ENDIF}
|
||||||
|
Interfaces, // this includes the LCL widgetset
|
||||||
|
Forms
|
||||||
|
{ add your units here }, WaitForUnit1;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Application.Initialize;
|
||||||
|
Application.CreateForm(TForm1, Form1);
|
||||||
|
Application.Run;
|
||||||
|
end.
|
||||||
|
|
||||||
32
examples/multithreading/waitforunit1.lfm
Normal file
32
examples/multithreading/waitforunit1.lfm
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
object Form1: TForm1
|
||||||
|
ActiveControl = Button1
|
||||||
|
Caption = 'Form1'
|
||||||
|
ClientHeight = 359
|
||||||
|
ClientWidth = 394
|
||||||
|
OnCreate = FormCreate
|
||||||
|
OnDestroy = FormDestroy
|
||||||
|
PixelsPerInch = 75
|
||||||
|
HorzScrollBar.Page = 393
|
||||||
|
VertScrollBar.Page = 358
|
||||||
|
Left = 286
|
||||||
|
Height = 359
|
||||||
|
Top = 202
|
||||||
|
Width = 394
|
||||||
|
object Button1: TButton
|
||||||
|
BorderSpacing.InnerBorder = 4
|
||||||
|
Caption = 'Start'
|
||||||
|
OnClick = Button1Click
|
||||||
|
TabOrder = 0
|
||||||
|
Left = 32
|
||||||
|
Height = 25
|
||||||
|
Top = 16
|
||||||
|
Width = 75
|
||||||
|
end
|
||||||
|
object Memo1: TMemo
|
||||||
|
Align = alBottom
|
||||||
|
TabOrder = 1
|
||||||
|
Height = 303
|
||||||
|
Top = 56
|
||||||
|
Width = 394
|
||||||
|
end
|
||||||
|
end
|
||||||
13
examples/multithreading/waitforunit1.lrs
Normal file
13
examples/multithreading/waitforunit1.lrs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{ Dies ist eine automatisch erzeugte Lazarus-Ressourcendatei }
|
||||||
|
|
||||||
|
LazarusResources.Add('TForm1','FORMDATA',[
|
||||||
|
'TPF0'#6'TForm1'#5'Form1'#13'ActiveControl'#7#7'Button1'#7'Caption'#6#5'Form1'
|
||||||
|
+#12'ClientHeight'#3'g'#1#11'ClientWidth'#3#138#1#8'OnCreate'#7#10'FormCreate'
|
||||||
|
+#9'OnDestroy'#7#11'FormDestroy'#13'PixelsPerInch'#2'K'#18'HorzScrollBar.Page'
|
||||||
|
+#3#137#1#18'VertScrollBar.Page'#3'f'#1#4'Left'#3#30#1#6'Height'#3'g'#1#3'Top'
|
||||||
|
+#3#202#0#5'Width'#3#138#1#0#7'TButton'#7'Button1'#25'BorderSpacing.InnerBord'
|
||||||
|
+'er'#2#4#7'Caption'#6#5'Start'#7'OnClick'#7#12'Button1Click'#8'TabOrder'#2#0
|
||||||
|
+#4'Left'#2' '#6'Height'#2#25#3'Top'#2#16#5'Width'#2'K'#0#0#5'TMemo'#5'Memo1'
|
||||||
|
+#5'Align'#7#8'alBottom'#8'TabOrder'#2#1#6'Height'#3'/'#1#3'Top'#2'8'#5'Width'
|
||||||
|
+#3#138#1#0#0#0
|
||||||
|
]);
|
||||||
162
examples/multithreading/waitforunit1.pas
Normal file
162
examples/multithreading/waitforunit1.pas
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
{
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This source is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This code is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* A copy of the GNU General Public License is available on the World *
|
||||||
|
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||||
|
* obtain it by writing to the Free Software Foundation, *
|
||||||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
* *
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
Demo to show, how a Thread waits for another.
|
||||||
|
}
|
||||||
|
unit WaitForUnit1;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, Buttons,
|
||||||
|
StdCtrls, LCLProc;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TBaseThread }
|
||||||
|
|
||||||
|
TBaseThread = class(TThread)
|
||||||
|
public
|
||||||
|
procedure Log(const Msg: string; AppendLineEnd: boolean = true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TThreadA }
|
||||||
|
|
||||||
|
TThreadA = class(TBaseThread)
|
||||||
|
public
|
||||||
|
WaitForB: PRtlEvent;
|
||||||
|
procedure Execute; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TThreadB }
|
||||||
|
|
||||||
|
TThreadB = class(TBaseThread)
|
||||||
|
private
|
||||||
|
FCounter: integer;
|
||||||
|
public
|
||||||
|
procedure Execute; override;
|
||||||
|
property Counter: integer read FCounter write FCounter;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TForm1 }
|
||||||
|
|
||||||
|
TForm1 = class(TForm)
|
||||||
|
Button1: TButton;
|
||||||
|
Memo1: TMemo;
|
||||||
|
procedure Button1Click(Sender: TObject);
|
||||||
|
procedure FormCreate(Sender: TObject);
|
||||||
|
procedure FormDestroy(Sender: TObject);
|
||||||
|
private
|
||||||
|
ACriticalSection: TRTLCriticalSection;
|
||||||
|
MsgText: string;
|
||||||
|
procedure AddMessage;
|
||||||
|
public
|
||||||
|
ThreadA: TThreadA;
|
||||||
|
ThreadB: TThreadB;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
Form1: TForm1;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ TForm1 }
|
||||||
|
|
||||||
|
procedure TForm1.Button1Click(Sender: TObject);
|
||||||
|
begin
|
||||||
|
if ThreadA=nil then
|
||||||
|
ThreadA:=TThreadA.Create(false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.FormCreate(Sender: TObject);
|
||||||
|
begin
|
||||||
|
InitCriticalSection(ACriticalSection);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.FormDestroy(Sender: TObject);
|
||||||
|
begin
|
||||||
|
DoneCriticalsection(ACriticalSection);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TForm1.AddMessage;
|
||||||
|
begin
|
||||||
|
Memo1.Lines.Text:=MsgText;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TThreadA }
|
||||||
|
|
||||||
|
procedure TThreadA.Execute;
|
||||||
|
begin
|
||||||
|
Form1.ThreadB:=TThreadB.Create(false);
|
||||||
|
// create event
|
||||||
|
WaitForB:=RTLEventCreate;
|
||||||
|
while not Application.Terminated do begin
|
||||||
|
Log('A: wait for B ...');
|
||||||
|
// wait infinitely (until B wakes A)
|
||||||
|
RtlEventWaitFor(WaitForB);
|
||||||
|
Log('A: ThreadB.Counter='+IntToStr(Form1.ThreadB.Counter));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TThreadB }
|
||||||
|
|
||||||
|
procedure TThreadB.Execute;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Counter:=0;
|
||||||
|
while not Application.Terminated do begin
|
||||||
|
Log('B: Working ...');
|
||||||
|
for i:=1 to 5 do begin
|
||||||
|
Sleep(300);
|
||||||
|
Log('..... ',false);
|
||||||
|
end;
|
||||||
|
Log('');
|
||||||
|
inc(Counter);
|
||||||
|
Log('B: Wake A');
|
||||||
|
// wake A
|
||||||
|
RtlEventSetEvent(Form1.ThreadA.WaitForB);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TBaseThread }
|
||||||
|
|
||||||
|
procedure TBaseThread.Log(const Msg: string; AppendLineEnd: boolean);
|
||||||
|
var
|
||||||
|
s: String;
|
||||||
|
begin
|
||||||
|
EnterCriticalsection(Form1.ACriticalSection);
|
||||||
|
s:=Msg;
|
||||||
|
if AppendLineEnd then
|
||||||
|
s:=s+LineEnding;
|
||||||
|
dbgout(s);
|
||||||
|
Form1.MsgText:=Form1.MsgText+s;
|
||||||
|
Synchronize(@Form1.AddMessage);
|
||||||
|
LeaveCriticalsection(Form1.ACriticalSection);
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
{$I waitforunit1.lrs}
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user