P
programmer8329
Нашел следующую справку вроде все просто
Waiting for a task to be completed
Sometimes, you need to wait for a thread to finish some operation rather than
waiting for a particular thread to complete execution. To do this, use an event object.
Event objects (TEvent) should be created with global scope so that they can act like
signals that are visible to all threads.
When a thread completes an operation that other threads depend on, it calls
TEvent.SetEvent. SetEvent turns on the signal, so any other thread that checks will
know that the operation has completed. To turn off the signal, use the ResetEvent
method.
For example, consider a situation where you must wait for several threads to
complete their execution rather than a single thread. Because you don’t know which
thread will finish last, you can’t simply use the WaitFor method of one of the threads.
Instead, you can have each thread increment a counter when it is finished, and have
the last thread signal that they are all done by setting an event.
The following code shows the end of the OnTerminate event handler for all of the
threads that must complete. CounterGuard is a global critical section object that
prevents multiple threads from using the counter at the same time. Counter is a global
variable that counts the number of threads that have completed.
procedure TDataModule.TaskThreadTerminate(Sender: TObject);
begin
ƒ
CounterGuard.Acquire; { obtain a lock on the counter }
Dec(Counter); { decrement the global counter variable }
if Counter = 0 then
Event1.SetEvent; { signal if this is the last thread }
CounterGuard.Release; { release the lock on the counter }
ƒ
end;
The main thread initializes the Counter variable, launches the task threads, and waits
for the signal that they are all done by calling the WaitFor method. WaitFor waits for a
specified time period for the signal to be set, and returns one of the values from Table
The following shows how the main thread launches the task threads and then
resumes when they have all completed:
Event1.ResetEvent; { clear the event before launching the threads }
for i := 1 to Counter do
TaskThread.Create(False); { create and launch task threads }
if Event1.WaitFor(20000) <> wrSignaled then
raise Exception;
{ now continue with the main thread. All task threads have finished }
Note If you do not want to stop waiting for an event after a specified time period, pass the
WaitFor method a parameter value of INFINITE. Be careful when using INFINITE,
because your thread will hang if the anticipated signal is never received.
Это уже мой код
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,SyncObjs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure DoWork1(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TMyThread1 = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
TMyThread2 = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
var
Form1: TForm1;
T1 : TMyThread1;
T2 : TMyThread2;
event:tevent;
Counter:integer;
CounterGuard:TCriticalSection;
implementation
{$R *.dfm}
procedure TMyThread1.Execute;
begin
Synchronize(DoWork);
end;
procedure TMyThread2.Execute;
begin
Synchronize(DoWork);
end;
procedure TMyThread1.DoWork;
begin
Form1.CheckBox1.Checked := false;
end;
procedure TMyThread2.DoWork;
begin
Form1.CheckBox1.Checked := false;
end;
procedure Tform1.DoWork1(Sender: TObject);
begin
CounterGuard.Acquire; { obtain a lock on the counter }
Dec(Counter); { decrement the global counter variable }
if Counter = 0 then
event.SetEvent; { signal if this is the last thread }
CounterGuard.Release; { release the lock on the counter }
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Event.ResetEvent;
T2 := TMyThread2.Create(False);
T1 := TMyThread1.Create(False);
T2.OnTerminate:=DoWork1;
T1.OnTerminate:=DoWork1;
if event.WaitFor(infinite)=wrSignaled then
showmessage('done');
Button1.Caption := 'Stop';
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
event:=tevent.Create(nil,true,true,'');
Counter:=2;
end;
initialization
CounterGuard:=Tcriticalsection.Create;
end.
Но этот код не работает. я что нибудь сделал не так?. Помогите. Он не сигналит когда потоки прекращают работать
Waiting for a task to be completed
Sometimes, you need to wait for a thread to finish some operation rather than
waiting for a particular thread to complete execution. To do this, use an event object.
Event objects (TEvent) should be created with global scope so that they can act like
signals that are visible to all threads.
When a thread completes an operation that other threads depend on, it calls
TEvent.SetEvent. SetEvent turns on the signal, so any other thread that checks will
know that the operation has completed. To turn off the signal, use the ResetEvent
method.
For example, consider a situation where you must wait for several threads to
complete their execution rather than a single thread. Because you don’t know which
thread will finish last, you can’t simply use the WaitFor method of one of the threads.
Instead, you can have each thread increment a counter when it is finished, and have
the last thread signal that they are all done by setting an event.
The following code shows the end of the OnTerminate event handler for all of the
threads that must complete. CounterGuard is a global critical section object that
prevents multiple threads from using the counter at the same time. Counter is a global
variable that counts the number of threads that have completed.
procedure TDataModule.TaskThreadTerminate(Sender: TObject);
begin
ƒ
CounterGuard.Acquire; { obtain a lock on the counter }
Dec(Counter); { decrement the global counter variable }
if Counter = 0 then
Event1.SetEvent; { signal if this is the last thread }
CounterGuard.Release; { release the lock on the counter }
ƒ
end;
The main thread initializes the Counter variable, launches the task threads, and waits
for the signal that they are all done by calling the WaitFor method. WaitFor waits for a
specified time period for the signal to be set, and returns one of the values from Table
The following shows how the main thread launches the task threads and then
resumes when they have all completed:
Event1.ResetEvent; { clear the event before launching the threads }
for i := 1 to Counter do
TaskThread.Create(False); { create and launch task threads }
if Event1.WaitFor(20000) <> wrSignaled then
raise Exception;
{ now continue with the main thread. All task threads have finished }
Note If you do not want to stop waiting for an event after a specified time period, pass the
WaitFor method a parameter value of INFINITE. Be careful when using INFINITE,
because your thread will hang if the anticipated signal is never received.
Это уже мой код
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,SyncObjs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure DoWork1(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TMyThread1 = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
TMyThread2 = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
var
Form1: TForm1;
T1 : TMyThread1;
T2 : TMyThread2;
event:tevent;
Counter:integer;
CounterGuard:TCriticalSection;
implementation
{$R *.dfm}
procedure TMyThread1.Execute;
begin
Synchronize(DoWork);
end;
procedure TMyThread2.Execute;
begin
Synchronize(DoWork);
end;
procedure TMyThread1.DoWork;
begin
Form1.CheckBox1.Checked := false;
end;
procedure TMyThread2.DoWork;
begin
Form1.CheckBox1.Checked := false;
end;
procedure Tform1.DoWork1(Sender: TObject);
begin
CounterGuard.Acquire; { obtain a lock on the counter }
Dec(Counter); { decrement the global counter variable }
if Counter = 0 then
event.SetEvent; { signal if this is the last thread }
CounterGuard.Release; { release the lock on the counter }
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Event.ResetEvent;
T2 := TMyThread2.Create(False);
T1 := TMyThread1.Create(False);
T2.OnTerminate:=DoWork1;
T1.OnTerminate:=DoWork1;
if event.WaitFor(infinite)=wrSignaled then
showmessage('done');
Button1.Caption := 'Stop';
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
event:=tevent.Create(nil,true,true,'');
Counter:=2;
end;
initialization
CounterGuard:=Tcriticalsection.Create;
end.
Но этот код не работает. я что нибудь сделал не так?. Помогите. Он не сигналит когда потоки прекращают работать