Recent

Author Topic: Pausing of threads  (Read 4641 times)

kapibara

  • Hero Member
  • *****
  • Posts: 610
Pausing of threads
« on: August 01, 2014, 02:58:28 am »
Suspend and Resume is deprecated, so I added two procedures, Pause and UnPause, to the thread.

It seems to work fine, but question is: I dont know if this code is safer than the old way? If it is, could someone tell me why?  :)

Here's how it works: When the Pause procedure is called, the selected thread enters its own critical section. But thats not what pauses the execution. So what happens next is that the threads Execute procedure tries to get into the same critical section (because a Paused flag was set to true in the Pause procedure) but the critical section is already occupied so it can't be entered. Result: the thread sleeps until UnPause is called and the thread "resumes" as before)

Demo attached, and the thread code:

EDIT: removed the callbacks to make it easier to read.

Code: [Select]
unit uThread;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

type

  { TMyThread }
  TMyThread = class(TThread)
  private
    FPaused: Boolean;
    FCriticalSection: TRTLCriticalSection;
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended: Boolean);
    destructor Destroy; override;
    procedure Pause;
    procedure UnPause;
    property Paused: Boolean read FPaused write FPaused;
  end;

implementation

uses
  Dialogs, Forms;

{ TMyThread }

constructor TMyThread.Create(CreateSuspended: Boolean);
begin
  InitCriticalSection(FCriticalSection);
  inherited Create(CreateSuspended);
end;

destructor TMyThread.Destroy;
begin
  DoneCriticalsection(FCriticalSection);
  inherited Destroy;
end;

procedure TMyThread.Pause;
begin
  EnterCriticalsection(FCriticalSection);
  FPaused:=True;
end;

procedure TMyThread.UnPause;
begin
  FPaused:=False;
  LeaveCriticalsection(FCriticalSection);
end;

procedure TMyThread.Execute;
begin
  repeat
    if Terminated then
    begin
      if FPaused then UnPause;
      Break;
    end;

    ..Do some job here...

    if FPaused then
      EnterCriticalsection(FCriticalSection);

    LeaveCriticalsection(FCriticalSection);
    Sleep(10);
  until False;
end;

end.
« Last Edit: August 01, 2014, 05:34:32 am by kapibara »
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

Fred vS

  • Hero Member
  • *****
  • Posts: 3168
    • StrumPract is the musicians best friend
Re: Pausing of threads
« Reply #1 on: August 01, 2014, 03:58:37 am »
Hello.

You may also use Events to pause threads.

See the excellent example of KpjComp  ;) :=>

http://forum.lazarus.freepascal.org/index.php/topic,18921.msg107167.html?PHPSESSID=b52538f089a2247187e8383a7cdd64e3#msg107167
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

kapibara

  • Hero Member
  • *****
  • Posts: 610
Re: Pausing of threads
« Reply #2 on: August 01, 2014, 05:52:09 am »
@Fred VS: Thank you, have tried KpjComp's example now. I should perhaps use that method instead.

It would still be interesting if someone could comment my code. Now I believe it is safe, because all work is done before pausing takes place, so no resources should stay locked:

"The reason Suspend and Resume are deprecated is because there are no guarantees at what point in the execution the thread will be suspended on."
"Suspend was dangerous because it could suspend the thread while it was holding
a lock on a mutex - a recipe for deadlocks."
Lazarus trunk / fpc 3.2.2 / Kubuntu 22.04 - 64 bit

hinst

  • Sr. Member
  • ****
  • Posts: 303
Re: Pausing of threads
« Reply #3 on: August 01, 2014, 10:31:58 am »
Code: [Select]
repeat
  if not Paused then
    doTheJob;
  Sleep(0);
until Terminated;

Suspend & Resume methods do an eternily different thing, they pause the thread no matter what it does
I know one thing what they are good for: if you want, for example, some particular thread to consume approximately this much of CPU time (10%, for example), then you can easily do this with suspend & resume by suspending it for 90 milliseconds and then resuming it for 10 milliseconds
« Last Edit: August 01, 2014, 10:35:14 am by hinst »
Too late to escape fate

 

TinyPortal © 2005-2018