1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
| unit Unit6;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
const
LM_LOG = WM_USER;
type
TThreadA = class(TThread)
protected
procedure Execute; override;
end;
TThreadB = class(TThread)
protected
procedure Execute; override;
public
Counter :integer;
end;
TForm6 = class(TForm)
Memo1: TMemo;
bStart: TButton;
bStop: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure bStartClick(Sender: TObject);
procedure bStopClick(Sender: TObject);
private
ThreadA :TThreadA;
procedure LMLog(var Message :TMessage); message LM_LOG;
end;
var
Form6: TForm6;
implementation
uses System.SyncObjs;
const
A_WaitForB = 1;
A_Counter = 2;
B_Working = 3;
B_Running = 4;
B_WakeA = 5;
var
Wnd : THandle;
CSPause : TCriticalSection;
WaitRunning : TEvent;
WaitFinish : TEvent;
{$R *.dfm}
procedure TForm6.bStartClick(Sender: TObject);
begin
CSPause.Leave;
end;
procedure TForm6.bStopClick(Sender: TObject);
begin
CSPause.Enter;
end;
procedure TForm6.FormCreate(Sender: TObject);
begin
CSPause.Enter;
Wnd := Handle;
ThreadA := TThreadA.Create(FALSE);
end;
procedure TForm6.FormDestroy(Sender: TObject);
begin
CSPause.Leave;
ThreadA.Terminate;
ThreadA.WaitFor;
ThreadA.Free;
end;
procedure TForm6.LMLog(var Message: TMessage);
begin
case Message.WParam of
A_WaitForB : Memo1.Lines.Add('A: wait for B ...');
A_Counter : Memo1.Lines.Add(Format('A: ThreadB.Counter=%d', [Message.LParam]));
B_Working : Memo1.Lines.Add('B: Working ...');
B_Running : Memo1.Lines[Memo1.Lines.Count -1] := Memo1.Lines[Memo1.Lines.Count -1] +' ...';
B_WakeA : Memo1.Lines.Add('B: Wake A');
end;
end;
{ TThreadA }
procedure TThreadA.Execute;
var
ThreadB :TThreadB;
begin
ThreadB := TThreadB.Create(False);
try
while not Terminated do
begin
// Attend Start (mais ne conserve pas le verrou)
CSPause.Enter;
CSPause.Leave;
WaitRunning.SetEvent;
// Attend la fin de B
PostMessage(Wnd, LM_LOG, A_WaitForB, 0);
WaitFinish.WaitFor;
PostMessage(Wnd, LM_LOG, A_Counter, ThreadB.Counter);
// B terminé !
end;
finally
WaitRunning.SetEvent;
ThreadB.Free;
end;
end;
{ TThreadB }
procedure TThreadB.Execute;
var
i: Integer;
begin
while not Terminated do
begin
// Attend Start
WaitRunning.WaitFor;
PostMessage(Wnd, LM_LOG, B_Working, 0);
for i := 1 to 5 do
begin
Sleep(300);
PostMessage(Wnd, LM_LOG, B_Running, 0);
end;
Counter := Counter + 1;
// Signale la fin
PostMessage(Wnd, LM_LOG, B_WakeA, 1);
WaitFinish.SetEvent;
end;
end;
initialization
CSPause := TCriticalSection.Create;
WaitRunning := TEvent.Create(nil, FALSE, FALSE, '');
WaitFinish := TEvent.Create(nil, FALSE, FALSE, '');
finalization
CSPause.Free;
WaitRunning.Free;
WaitFinish.Free;
end. |
Partager