Em especial se houver seções críticas entre as threads. Ao suspender uma thread que esteja dentro de uma seção crítica, essa seção crítica não será liberada!
Bolei um exemplo sobre o assunto, segue abaixo o pas e o dfm.
unit Unt_Principal;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SyncObjs, Buttons, StdCtrls;
type
TMinhaThread = class(TThread)
private
FNome : string;
FLog : string;
protected
procedure QuandoTerminar(Sender: TObject);
public
constructor Create(psNome: string); reintroduce;
procedure Execute; override;
procedure GerarLog(psLog: string);
procedure GerarLogSincronizado;
end;
TfPrincipal = class(TForm)
btnA: TButton;
btnB: TBitBtn;
btnSuspendA: TButton;
btnSuspendB: TBitBtn;
mmo1: TMemo;
btnTerminateA: TButton;
btnTerminateB: TBitBtn;
btnLiberarSC: TBitBtn;
procedure btnAClick(Sender: TObject);
procedure btnBClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btnSuspendAClick(Sender: TObject);
procedure btnSuspendBClick(Sender: TObject);
procedure btnTerminateAClick(Sender: TObject);
procedure btnTerminateBClick(Sender: TObject);
procedure btnLiberarSCClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
fPrincipal : TfPrincipal;
ThreadA : TMinhaThread;
ThreadB : TMinhaThread;
SecaoCritica : TCriticalSection;
implementation
{$R *.dfm}
{ TMinhaThread }
constructor TMinhaThread.Create(psNome: string);
begin
inherited Create(True);
Self.FNome := psNome;
Self.OnTerminate := Self.QuandoTerminar;
end;
procedure TMinhaThread.Execute;
begin
inherited;
try
while not (Self.Terminated) do
begin
Sleep(10);
Self.GerarLog(Format('%s vai entrar na seção critica',[Self.FNome]));
SecaoCritica.Enter;
Self.GerarLog(Format('%s entrou na seção critica',[Self.FNome]));
while not (Self.Terminated) do
begin
Sleep(10);
Application.ProcessMessages;
end;
end;
finally
Self.GerarLog(Format('%s vai sair da seção critica',[Self.FNome]));
SecaoCritica.Release;
Self.GerarLog(Format('%s saiu da seção critica',[Self.FNome]));
end;
end;
procedure TMinhaThread.GerarLog(psLog: string);
begin
Self.FLog := psLog;
Self.Synchronize(Self.GerarLogSincronizado);
end;
procedure TMinhaThread.GerarLogSincronizado;
begin
fPrincipal.mmo1.Lines.Add(Self.FLog);
end;
procedure TMinhaThread.QuandoTerminar(Sender: TObject);
begin
Self.GerarLog(Format('%s terminando',[Self.FNome]));
end;
procedure TfPrincipal.btnAClick(Sender: TObject);
begin
ThreadA.Start;
end;
procedure TfPrincipal.btnBClick(Sender: TObject);
begin
ThreadB.Start;
end;
procedure TfPrincipal.btnLiberarSCClick(Sender: TObject);
begin
SecaoCritica.Release;
end;
procedure TfPrincipal.btnSuspendAClick(Sender: TObject);
begin
ThreadA.Suspend;
end;
procedure TfPrincipal.btnSuspendBClick(Sender: TObject);
begin
ThreadB.Suspend;
end;
procedure TfPrincipal.btnTerminateAClick(Sender: TObject);
begin
ThreadA.Terminate;
if not (ThreadA.Suspended) then
ThreadA.WaitFor;
end;
procedure TfPrincipal.btnTerminateBClick(Sender: TObject);
begin
ThreadB.Terminate;
if not (ThreadB.Suspended) then
ThreadB.WaitFor;
end;
procedure TfPrincipal.FormCreate(Sender: TObject);
begin
ThreadA := TMinhaThread.Create('A');
ThreadB := TMinhaThread.Create('B');
SecaoCritica := TCriticalSection.Create;
end;
end.
object fPrincipal: TfPrincipal Left = 0 Top = 0 Caption = 'Prova de Conceito' ClientHeight = 217 ClientWidth = 589 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'Tahoma' Font.Style = [] OldCreateOrder = False OnCreate = FormCreate PixelsPerInch = 96 TextHeight = 13 object btnA: TButton Left = 8 Top = 8 Width = 75 Height = 25 Caption = 'Thread A' TabOrder = 0 OnClick = btnAClick end object btnB: TBitBtn Left = 8 Top = 55 Width = 75 Height = 25 Caption = 'Thread B' DoubleBuffered = True ParentDoubleBuffered = False TabOrder = 1 OnClick = btnBClick end object btnSuspendA: TButton Left = 89 Top = 8 Width = 75 Height = 25 Caption = 'Suspend' TabOrder = 2 OnClick = btnSuspendAClick end object btnSuspendB: TBitBtn Left = 89 Top = 55 Width = 75 Height = 25 Caption = 'Suspend' DoubleBuffered = True ParentDoubleBuffered = False TabOrder = 3 OnClick = btnSuspendBClick end object mmo1: TMemo Left = 260 Top = 8 Width = 321 Height = 185 Lines.Strings = ( 'mmo1') TabOrder = 4 end object btnTerminateA: TButton Left = 170 Top = 8 Width = 75 Height = 25 Caption = 'Terminate' TabOrder = 5 OnClick = btnTerminateAClick end object btnTerminateB: TBitBtn Left = 170 Top = 55 Width = 75 Height = 25 Caption = 'Terminate' DoubleBuffered = True ParentDoubleBuffered = False TabOrder = 6 OnClick = btnTerminateBClick end object btnLiberarSC: TBitBtn Left = 8 Top = 104 Width = 237 Height = 25 Caption = 'Liberar SC' DoubleBuffered = True ParentDoubleBuffered = False TabOrder = 7 OnClick = btnLiberarSCClick end end