Deprecated Delphi TThread.Suspend

I've noticed that the TThread.Suspend and Resume methods have been deprecated in Delphi XE2. I would like to see an sample of what would be an appropriate replacement for them. I have included a sample program that contains logic I use quite a bit. It is simply a running clock in a TStatusBar component that updates every second using Synchronize to allow the thread to update the form. Usually this is the only additional thread in my application, however that is not always the case. Here is the code and thank you for any appropriate Suspend/Resume code replacement:

unit DemoFrm;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls,
  Vcl.ExtCtrls;

const
     WM_APPSTARTUP               = WM_USER + 1;

type
  TDemoForm = class(TForm)
    StatusBar: TStatusBar;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    procedure WMAppStartup(var Msg: TMessage); message WM_APPSTARTUP;
    procedure ClockTick(Sender: TObject);
    procedure UpdateStatusBar(aIndex: Integer; aMsg: String);
  public
    { Public declarations }
  end;

  TClockThread = class(TTHread)
  private
    procedure UpdateStatus;
  public
    procedure Execute; override;
  end;

var
  DemoForm: TDemoForm;

implementation

{$R *.dfm}

var
   ClockTID:           TClockThread;
   ClockTimer:         TTimer;

procedure TClockThread.UpdateStatus;
begin
     if ((Assigned(DemoForm)) and (Assigned(ClockTimer))) then
       begin
       with (DemoForm) do
         begin
         UpdateStatusBar(0,FormatDateTime('h:nn:ss am/pm',Now));
         end;
       end;
end;

procedure TClockThread.Execute;
begin
     while (TRUE) do
       begin
       Synchronize(UpdateStatus);
       Suspend;
       end;
end;

procedure TDemoForm.WMAppStartup(var Msg: TMessage);
begin
     Update;
     ClockTimer.Enabled := TRUE;
end;

procedure TDemoForm.ClockTick(Sender: TObject);
begin
     if (Assigned(ClockTID)) then
       ClockTID.Resume;
end;

procedure TDemoForm.UpdateStatusBar(aIndex: Integer; aMsg: String);
begin
     if (aIndex < StatusBar.Panels.Count) then
       begin
       StatusBar.Panels[aIndex].Text := aMsg;
       StatusBar.Update;
       end;
end;

procedure TDemoForm.FormCreate(Sender: TObject);
begin
     ClockTID := TClockThread.Create(FALSE);
     ClockTimer := TTimer.Create(nil);
     ClockTimer.Enabled := FALSE;
     ClockTimer.Interval := 1000;
     ClockTimer.OnTimer := ClockTick;
end;

procedure TDemoForm.FormDestroy(Sender: TObject);
begin
     if (Assigned(ClockTimer)) then ClockTimer.Free;
end;

procedure TDemoForm.FormShow(Sender: TObject);
begin
     PostMessage(Handle,WM_APPSTARTUP,0,0);
end;

end.

// DFM
object DemoForm: TDemoForm
  Left = 0
  Top = 0
  Caption = 'Status Clock Demo'
  ClientHeight = 297
  ClientWidth = 383
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object StatusBar: TStatusBar
    Left = 0
    Top = 278
    Width = 383
    Height = 19
    Panels = <
      item
        Alignment = taCenter
        Width = 90
      end
      item
        Width = 50
      end>
  end
end

Open in new window

LVL 1
softbreezeAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gskoczylasSenior Software DeveloperCommented:
According to the Help for Delphi XE they suggest to use the TEvent component instead of the Suspend and Resume methods.
0
karagunesCommented:
You can use Win Api if you like. So try the code below I wrote:

{$IFDEF WIN64}
  function Wow64SuspendThread(hThread: THandle): DWord; stdcall; external 'Kernel32.dll';
  {$ELSE}
  function SuspendThread(hThread: THandle): DWord; stdcall; external 'Kernel32.dll';
  {$ENDIF}
  function ResumeThread(hThread: THandle): DWord; stdcall; external 'Kernel32.dll';

var
  Form1: TForm1;

implementation

{$R *.dfm}

function MySuspendThread(hThread: THandle): DWord;
begin
  {$IFDEF WIN64}
  Result := Wow64SuspendThread(hThread);
  {$ELSE}
  Result := SuspendThread(hThread);
  {$ENDIF}
end;

function MyResumeThread(hThread: THandle): DWord;
begin
  Result := ResumeThread(hThread);
end;

// here is how to use

procedure TForm1.FormCreate(Sender: TObject);
var
  i: DWord;
begin
  i := MySuspendThread(MyThreadID);
  if i <> High(DWord) then
    Caption := 'OK'
  else
    Caption := 'Error';

  i := MyResumeThread(MyThreadID);
  if i <> High(DWord) then
    Caption := 'OK'
  else
    Caption := 'Error';


end;

Open in new window

0
softbreezeAuthor Commented:
Thank you, karagunes! You'll get the points. I will release them to you tomorrow after I take a closer look at your example.
Over the weekend I found some articles and created some sample code that use the TEvent.SetEvent/ResetEvent as well as PostMessage calls. From them I was able to accomplish what I was trying to do.

I'd like to post the code to the site, just in case in the future I go looking for this again.
Thanks again
0
Geert GOracle dbaCommented:
the replacement for resume and suspend is Start and Stop procedures within TThread resp.

your concept is off
> you are using the main thread to wait for a second to call update  statusbar
> the main thread can be too busy to call the update
> trying moving the mouse continuously around the form to see

Why do you need to put a extra timer in the form ?
You can simply use sleep(1000) within the thread
 
unit DemoFrm;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls,
  Vcl.ExtCtrls;

type
  TClockThread = class(TTHread)
  private
    fUpdateProc: TNotifyEvent;
    procedure UpdateStatus;
  public
    constructor Create(aUpdateProc: TNotifyEvent);
    procedure Execute; override;
  end;

  TDemoForm = class(TForm)
    StatusBar: TStatusBar;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    fClockTID: TClockThread;
    procedure UpdateStatusBar(aStatusBar: TStatusBar; aIndex: Integer; aMsg: String);
    procedure UpdateStatusBarClock(Sender: TObject);
  end;

var
  DemoForm: TDemoForm;

implementation

{$R *.dfm}

constructor TClockThread.Create(aUpdateProc: TNotifiyEvent);
begin
  inherited Create(False);
  fUpdateProc := aUpdateProc;
  FreeOnTerminate := True;
end;

procedure TClockThread.UpdateStatus;
begin
  if Assigned(fUpdateProc) then 
    fUpdateProc(Self);
end;

procedure TClockThread.Execute;
begin
  while not Terminated do
  begin
    Synchronize(UpdateStatus);
    Sleep(1000);
  end;
end;

procedure TDemoForm.UpdateStatusBarClock(Sender: TObject);
begin
  UpdateStatusBar(StatusBar, 0, FormatDateTime('h:nn:ss am/pm',Now));
end;

procedure TDemoForm.UpdateStatusBar(aStatusBar, aIndex: Integer; aMsg: String);
begin
  if (aIndex >= 0) and (aIndex < aStatusBar.Panels.Count) then
  begin
    aStatusBar.Panels[aIndex].Text := aMsg;
    aStatusBar.Update;
  end;
end;

procedure TDemoForm.FormCreate(Sender: TObject);
begin
  fClockTID := TClockThread.Create(UpdateStatusBarClock);
end;

procedure TDemoForm.FormDestroy(Sender: TObject);
begin
  fClockTid.Terminate;
end;

end.

Open in new window


you are mixing background threading ideas within the main thread
i changed the variable from global to form private
and removed the clock tick idea
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
softbreezeAuthor Commented:
Thanks, Both of you answered my questions, Geert's answer actually was closer to what I was asking.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.