⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 agthread.pas

📁 Tread Component for Delphi
💻 PAS
字号:
unit agThread;

{$I AG.INC}

interface

uses Windows, Classes;

type
  TThreadEx = class (TThread)
  private
    FOnExecute: TNotifyEvent;
  protected
    procedure Execute; override;
  public
    property OnExecute: TNotifyEvent read FOnExecute write FOnExecute;
    property Terminated;
  end;

  TagThread = class (TComponent)
  private
    FThread: TThreadEx;
    FSyncMethod: TNotifyEvent;
    FSyncParams: Pointer;
    FStreamedSuspended, FCycled: Boolean;
    FOnExecute, FOnException: TNotifyEvent;
    FInterval: integer;
    procedure InternalSynchronize;
    function GetHandle: THandle;
    function GetThreadID: THandle;
    function GetOnTerminate: TNotifyEvent;
    procedure SetOnTerminate(Value: TNotifyEvent);
    function GetPriority: TThreadPriority;
    procedure SetPriority(Value: TThreadPriority);
    function GetReturnValue: Integer;
    procedure SetReturnValue(Value: Integer);
    function GetSuspended: Boolean;
    procedure SetSuspended(Value: Boolean);
    function GetTerminated: boolean;
  protected
    procedure DoExecute(Sender: TObject); virtual;
    procedure DoException(Sender: TObject); virtual;
    procedure Loaded; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Execute;
    procedure Synchronize(Method: TThreadMethod);
    procedure SynchronizeEx(Method: TNotifyEvent; Params: Pointer);
    procedure Suspend;
    procedure Resume;
    procedure Terminate;
    function TerminateWaitFor: Integer;
    procedure TerminateHard;
    function WaitFor: Integer;
    property ReturnValue: Integer read GetReturnValue write SetReturnValue;
    property Handle: THandle read GetHandle;
    property ThreadID: THandle read GetThreadID;
    property Terminated: Boolean read GetTerminated;
    procedure Delay(MSecs: Longint);
  published
    property OnTerminate: TNotifyEvent read GetOnTerminate write SetOnTerminate;
    property Priority: TThreadPriority read GetPriority write SetPriority;
    property Suspended: Boolean read GetSuspended write SetSuspended default True;
    property OnExecute: TNotifyEvent read FOnExecute write FOnExecute;
    property OnException: TNotifyEvent read FOnException write FOnException;
    property Interval: integer read FInterval write FInterval;
    property Cycled: boolean read FCycled write FCycled;
  end;

implementation

uses SysUtils, Forms;

procedure TThreadEx.Execute;
begin
  if Assigned(FOnExecute) then FOnExecute(Self);
end;

type
  TThreadHack = class (TThreadEx);

constructor TagThread.Create(AOwner: TComponent);
begin
  inherited;
  FStreamedSuspended := True;
  FThread := TThreadEx.Create(True);
  FThread.OnExecute := DoExecute;
  FInterval:=0;
  FCycled:=false;
end;

destructor TagThread.Destroy;
begin
  FThread.Free;
  inherited;
end;

procedure TagThread.DoExecute(Sender: TObject);
begin
  repeat
    Delay(FInterval);
    if FThread.Terminated then break;
    try
      if Assigned(FOnExecute) then FOnExecute(Self);
    except
      SynchronizeEx(DoException,ExceptObject);
    end;
  until FThread.Terminated or not(Cycled);
end;

procedure TagThread.DoException(Sender: TObject);
var
  s: string;
begin
  if Assigned(FOnException) then
    FOnException(Sender)
  else begin
    s:=Format('Thread %s raised exception class %s with message ''%s''.',
      [Name,Exception(Sender).ClassName,Exception(Sender).Message]);
    Application.MessageBox(PChar(s),PChar(Application.Title),
      MB_ICONERROR or MB_SETFOREGROUND or MB_APPLMODAL);
  end;
end;

function TagThread.GetHandle: THandle;
begin
  Result := FThread.Handle;
end;

function TagThread.GetOnTerminate: TNotifyEvent;
begin
  Result := FThread.OnTerminate;
end;

function TagThread.GetPriority: TThreadPriority;
begin
  Result := FThread.Priority;
end;

function TagThread.GetReturnValue: Integer;
begin
  Result := TThreadHack(FThread).ReturnValue;
end;

function TagThread.GetSuspended: Boolean;
begin
  if not (csDesigning in ComponentState) then
    Result := FThread.Suspended else
    Result := FStreamedSuspended;
end;

procedure TagThread.Execute;
begin
  TerminateHard;
  FThread.Resume;
end;

procedure TagThread.Loaded;
begin
  inherited;
  SetSuspended(FStreamedSuspended);
end;

procedure TagThread.SetOnTerminate(Value: TNotifyEvent);
begin
  FThread.OnTerminate := Value;
end;

procedure TagThread.SetPriority(Value: TThreadPriority);
begin
  FThread.Priority := Value;
end;

procedure TagThread.SetReturnValue(Value: Integer);
begin
  TThreadHack(FThread).ReturnValue := Value;
end;

procedure TagThread.SetSuspended(Value: Boolean);
begin
  if not (csDesigning in ComponentState) then
  begin
    if (csLoading in ComponentState) then
      FStreamedSuspended := Value else
      FThread.Suspended := Value;
  end else
    FStreamedSuspended := Value;
end;

procedure TagThread.Suspend;
begin
  FThread.Suspend;
end;

procedure TagThread.Synchronize(Method: TThreadMethod);
begin
  TThreadHack(FThread).Synchronize(Method);
end;

procedure TagThread.InternalSynchronize;
begin
  FSyncMethod(FSyncParams);
end;

procedure TagThread.SynchronizeEx(Method: TNotifyEvent; Params: Pointer);
begin
  if not Assigned(FSyncMethod) then
  begin
    FSyncMethod := Method; FSyncParams := Params;
    try
      TThreadHack(FThread).Synchronize(InternalSynchronize);
    finally
      FSyncMethod := nil; FSyncParams := nil;
    end;
  end;
end;

procedure TagThread.Resume;
begin
  FThread.Resume;
end;

procedure TagThread.Terminate;
begin
  FThread.Terminate;
end;

function TagThread.TerminateWaitFor: Integer;
begin
  Terminate;
  Result:=WaitFor;
end;

procedure TagThread.TerminateHard;
var
  FTmp: TThreadEx;
begin
  TerminateThread(FThread.Handle, 0);
  FTmp := TThreadEx.Create(True);
  try
    FTmp.Priority := Self.Priority;
    FTmp.OnExecute := DoExecute;
    FTmp.OnTerminate := Self.OnTerminate;
  except
    FTmp.Free;
    raise;
  end;
  FThread.Free;
  FThread := FTmp;
end;

function TagThread.WaitFor: Integer;
begin
  Result := FThread.WaitFor;
end;

function TagThread.GetTerminated: boolean;
begin
  Result:=FThread.Terminated;
end;

function TagThread.GetThreadID: THandle;
begin
  Result:=FThread.ThreadID;
end;

procedure TagThread.Delay(MSecs: Longint);
var
  FirstTickCount, Now: Longint;
begin
  if MSecs < 0 then exit;
  FirstTickCount := GetTickCount;
  repeat
    Sleep(1);
    Now := GetTickCount;
  until (Now - FirstTickCount >= MSecs) or (Now < FirstTickCount) or Terminated;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -