📄 dcthread.pas
字号:
{*******************************************************************************
Disk Controls pack v3.5
FILE: dcThread.pas - TdcEventThread class used in the dcDiskScanner and
dcMultiDiskScanner components.
Copyright (c) 1999-2002 UtilMind Solutions
All rights reserved.
E-Mail: info@appcontrols.com, info@utilmind.com
WWW: http://www.appcontrols.com, http://www.utilmind.com
The entire contents of this file is protected by International Copyright
Laws. Unauthorized reproduction, reverse-engineering, and distribution of all
or any portion of the code contained in this file is strictly prohibited and
may result in severe civil and criminal penalties and will be prosecuted to
the maximum extent possible under the law.
*******************************************************************************}
{$I umDefines.inc}
unit dcThread;
interface
uses
Windows, Classes, dcInternal;
type
TdcCustomThread = class;
{ TdcEventThread }
TdcEventThread = class
private
FHandle: THandle;
FThreadID: THandle;
FTerminated: Boolean;
FSuspended: Boolean;
FFreeOnTerminate: Boolean;
FReturnValue: Integer;
FRunning: Boolean;
FMethod: TThreadMethod;
FSynchronizeException: TObject;
// addons
FOnExecute,
FOnException,
FOnTerminate: TNotifyEvent;
// for internal use
Owner: TdcCustomThread;
function GetPriority: TThreadPriority;
procedure SetPriority(Value: TThreadPriority);
procedure SetSuspended(Value: Boolean);
// addons
procedure CallTerminate;
procedure CallException;
protected
procedure DoTerminate; //virtual;
procedure Execute; //virtual;
procedure Synchronize(Method: TThreadMethod);
property ReturnValue: Integer read FReturnValue write FReturnValue;
property Terminated: Boolean read FTerminated;
function CreateThread: TdcEventThread;
function RecreateThread: TdcEventThread;
public
constructor Create(aOwner: TdcCustomThread);
destructor Destroy; override;
procedure Resume;
procedure Suspend;
procedure Terminate;
function WaitFor:{$IFDEF D4}LongWord{$ELSE}Integer{$ENDIF};
property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;
property Handle: THandle read FHandle;
property Priority: TThreadPriority read GetPriority write SetPriority;
property Suspended: Boolean read FSuspended write SetSuspended;
property ThreadID: THandle read FThreadID;
property OnExecute: TNotifyEvent read FOnExecute write FOnExecute;
property OnException: TNotifyEvent read FOnException write FOnException;
property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
end;
{ TdcCustomThread }
TdcCustomThread = class(TumdcComponent)
private
FThread: TdcEventThread;
FDesignSuspended,
FHandleExceptions, // handle all exceptions within thread and do not raise them in the OnExecute event handler
FFreeOwnerOnTerminate: Boolean; // destroys owner on thread on terminate, if True. AK: July 6, 2002
FWaitThread: Boolean;
FWaitTimeout: Cardinal;
FOnWaitTimeoutExpired: TNotifyEvent;
{ for internal use }
FSyncMethod: TNotifyEvent;
FSyncParams: Pointer;
procedure InternalSynchronization;
function GetPriority: TThreadPriority;
procedure SetPriority(Value: TThreadPriority);
function GetSuspended: Boolean;
procedure SetSuspended(Value: Boolean);
function GetRunning: Boolean;
function GetTerminated: Boolean;
function GetThreadID: THandle;
function GetOnException: TNotifyEvent;
procedure SetOnException(Value: TNotifyEvent);
function GetOnExecute: TNotifyEvent;
procedure SetOnExecute(Value: TNotifyEvent);
function GetOnTerminate: TNotifyEvent;
procedure SetOnTerminate(Value: TNotifyEvent);
function GetHandle: THandle;
function GetReturnValue: Integer;
procedure SetReturnValue(Value: Integer);
protected
procedure Loaded; override;
procedure DoWaitTimeoutExpired; //virtual;
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
{ public methods and properties }
function Execute: Boolean; // virtual;
procedure Synchronize(Method: TThreadMethod); //virtual;
procedure SynchronizeEx(Method: TNotifyEvent; Params: Pointer); //virtual;
procedure Suspend;
procedure Resume;
procedure Terminate(Imediately: Boolean); //virtual;
function WaitFor:{$IFDEF D4}LongWord{$ELSE}Integer{$ENDIF};
property Handle: THandle read GetHandle;
property Running: Boolean read GetRunning;
property Terminated: Boolean read GetTerminated;
property ThreadID: THandle read GetThreadID;
property ReturnValue: Integer read GetReturnValue write SetReturnValue;
property FreeOwnerOnTerminate: Boolean read FFreeOwnerOnTerminate write FFreeOwnerOnTerminate default False;
// properties
property HandleExceptions: Boolean read FHandleExceptions write FHandleExceptions default True;
property Priority: TThreadPriority read GetPriority write SetPriority default tpNormal;
property Suspended: Boolean read GetSuspended write SetSuspended default True;
property WaitThread: Boolean read FWaitThread write FWaitThread default False;
property WaitTimeout: Cardinal read FWaitTimeout write FWaitTimeout default 0;
// events
property OnException: TNotifyEvent read GetOnException write SetOnException;
property OnExecute: TNotifyEvent read GetOnExecute write SetOnExecute;
property OnTerminate: TNotifyEvent read GetOnTerminate write SetOnTerminate;
property OnWaitTimeoutExpired: TNotifyEvent read FOnWaitTimeoutExpired write FOnWaitTimeoutExpired;
end;
{ TdcThread }
TdcThread = class(TdcCustomThread)
published
property HandleExceptions;
property Priority;
property Suspended;
property WaitThread;
property WaitTimeout;
property OnException;
property OnExecute;
property OnTerminate;
property OnWaitTimeoutExpired;
end;
implementation
uses Forms;
const
CM_EXECPROC = $8FFF;
CM_DESTROYWINDOW = $8FFE;
Priorities: Array[TThreadPriority] of Integer =
(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,
THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL);
type
PRaiseFrame = ^TRaiseFrame;
TRaiseFrame = record
NextRaise: PRaiseFrame;
ExceptAddr: Pointer;
ExceptObject: TObject;
ExceptionRecord: PExceptionRecord;
end;
var
ThreadLock: TRTLCriticalSection;
ThreadWindow: HWND;
ThreadCount: Integer;
{ Internal thread management routines }
function ThreadWndProc(Window: HWND; Message, wParam, lParam: Longint): Longint; stdcall;
begin
case Message of
CM_EXECPROC:
with TdcEventThread(lParam) do
begin
Result := 0;
if not (csDestroying in Owner.ComponentState) then
try
FSynchronizeException := nil;
FMethod;
except
{$WARNINGS OFF}
{$IFNDEF VER110}
if RaiseList <> nil then
begin
FSynchronizeException := PRaiseFrame(RaiseList)^.ExceptObject;
PRaiseFrame(RaiseList)^.ExceptObject := nil;
end;
{$ENDIF}
{$WARNINGS ON}
end;
end;
CM_DESTROYWINDOW:
begin
EnterCriticalSection(ThreadLock);
try
if (ThreadCount = 0) and (ThreadWindow <> 0) then
begin
DestroyWindow(ThreadWindow);
ThreadWindow := 0;
end;
finally
LeaveCriticalSection(ThreadLock);
end;
Result := 0;
end;
else
Result := DefWindowProc(Window, Message, wParam, lParam);
end;
end;
var
ThreadWindowClass: TWndClass = (
style: 0;
lpfnWndProc: @ThreadWndProc;
cbClsExtra: 0;
cbWndExtra: 0;
hInstance: 0;
hIcon: 0;
hCursor: 0;
hbrBackground: 0;
lpszMenuName: nil;
lpszClassName: 'TdcThreadWindow');
procedure AddThread;
function AllocateWindow: HWND;
var
TempClass: TWndClass;
ClassRegistered: Boolean;
begin
ThreadWindowClass.hInstance := HInstance;
ClassRegistered := GetClassInfo(HInstance, ThreadWindowClass.lpszClassName, TempClass);
if not ClassRegistered or (TempClass.lpfnWndProc <> @ThreadWndProc) then
begin
if ClassRegistered then
Windows.UnregisterClass(ThreadWindowClass.lpszClassName, HInstance);
Windows.RegisterClass(ThreadWindowClass);
end;
Result := CreateWindow(ThreadWindowClass.lpszClassName, '', 0,
0, 0, 0, 0, 0, 0, HInstance, nil);
end;
begin
EnterCriticalSection(ThreadLock);
try
if ThreadCount = 0 then
ThreadWindow := AllocateWindow;
Inc(ThreadCount);
finally
LeaveCriticalSection(ThreadLock);
end;
end;
procedure RemoveThread;
begin
EnterCriticalSection(ThreadLock);
try
Dec(ThreadCount);
if ThreadCount = 0 then
PostMessage(ThreadWindow, CM_DESTROYWINDOW, 0, 0);
finally
LeaveCriticalSection(ThreadLock);
end;
end;
function ThreadProc(Thread: TdcEventThread): Integer;
var
FreeThread: Boolean;
begin
Thread.FRunning := True;
try
Thread.Execute;
finally
FreeThread := Thread.FFreeOnTerminate;
Result := Thread.FReturnValue;
Thread.FRunning := False;
Thread.DoTerminate;
if FreeThread then Thread.Free;
EndThread(Result);
end;
end;
{ TdcEventThread }
constructor TdcEventThread.Create(aOwner: TdcCustomThread);
var
Flags: DWORD;
begin
inherited Create;
Owner := aOwner;
AddThread;
FSuspended := True; // always suspended after creation
Flags := CREATE_SUSPENDED;
FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), Flags, FThreadID);
end;
destructor TdcEventThread.Destroy;
begin
if FRunning and not Suspended then
begin
Terminate;
WaitFor;
end;
if FHandle <> 0 then CloseHandle(FHandle);
inherited;
RemoveThread;
end;
procedure TdcEventThread.DoTerminate;
begin
if Assigned(FOnTerminate) then
Synchronize(CallTerminate);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -