📄 threads.pas
字号:
unit Threads;
interface
uses Windows, Messages;
type
TThreadPriority = (tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest,
tpTimeCritical);
TThread = class
private
FHandle: THandle;
FThreadID: THandle;
FCreateSuspended: Boolean;
FTerminated: Boolean;
FSuspended: Boolean;
FFreeOnTerminate: Boolean;
FFinished: Boolean;
FReturnValue: Integer;
FFatalException: TObject;
function GetPriority: TThreadPriority;
procedure SetPriority(Value: TThreadPriority);
procedure SetSuspended(Value: Boolean);
protected
procedure CheckThreadError(ErrCode: Integer); overload;
procedure CheckThreadError(Success: Boolean); overload;
procedure Execute; virtual; abstract;
property ReturnValue: Integer read FReturnValue write FReturnValue;
property Terminated: Boolean read FTerminated;
public
constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
procedure AfterConstruction; override;
procedure Resume;
procedure Suspend;
procedure Terminate;
function WaitFor: LongWord;
property FatalException: TObject read FFatalException;
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;
end;
TServiceThread = class(TThread)
protected
procedure Initialize; virtual;
function GetState: Integer; virtual; abstract;
procedure Service(State: Integer); virtual; abstract;
procedure Finalize; virtual;
procedure Execute; override;
end;
TQueueThread = class(TThread)
protected
end;
implementation
uses SysUtils;
type
EThreadError = class(Exception);
const
SThreadCreateError = 'Thread creation error: %s';
SThreadError = 'Thread Error: %s (%d)';
function ThreadProc(Thread: TThread): Integer;
var
FreeThread: Boolean;
begin
try
if not Thread.Terminated then
try
Thread.Execute;
except
Thread.FFatalException := AcquireExceptionObject;
end;
finally
FreeThread := Thread.FFreeOnTerminate;
Result := Thread.FReturnValue;
Thread.FFinished := True;
if FreeThread then Thread.Free;
EndThread(Result);
end;
end;
constructor TThread.Create(CreateSuspended: Boolean);
begin
inherited Create;
FSuspended := CreateSuspended;
FCreateSuspended := CreateSuspended;
FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID);
if FHandle = 0 then
raise EThreadError.CreateFmt(SThreadCreateError, [SysErrorMessage(GetLastError)]);
end;
destructor TThread.Destroy;
begin
if (FThreadID <> 0) and not FFinished then
begin
Terminate;
if FCreateSuspended then
Resume;
WaitFor;
end;
if FHandle <> 0 then CloseHandle(FHandle);
inherited Destroy;
FFatalException.Free;
end;
procedure TThread.AfterConstruction;
begin
if not FCreateSuspended then
Resume;
end;
procedure TThread.CheckThreadError(ErrCode: Integer);
begin
if ErrCode <> 0 then
raise EThreadError.CreateFmt(SThreadError, [SysErrorMessage(ErrCode), ErrCode]);
end;
procedure TThread.CheckThreadError(Success: Boolean);
begin
if not Success then
CheckThreadError(GetLastError);
end;
const
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);
function TThread.GetPriority: TThreadPriority;
var
P: Integer;
I: TThreadPriority;
begin
P := GetThreadPriority(FHandle);
CheckThreadError(P <> THREAD_PRIORITY_ERROR_RETURN);
Result := tpNormal;
for I := Low(TThreadPriority) to High(TThreadPriority) do
if Priorities[I] = P then Result := I;
end;
procedure TThread.SetPriority(Value: TThreadPriority);
begin
CheckThreadError(SetThreadPriority(FHandle, Priorities[Value]));
end;
procedure TThread.SetSuspended(Value: Boolean);
begin
if Value <> FSuspended then
if Value then
Suspend
else
Resume;
end;
procedure TThread.Suspend;
var
OldSuspend: Boolean;
begin
OldSuspend := FSuspended;
try
FSuspended := True;
CheckThreadError(Integer(SuspendThread(FHandle)) >= 0);
except
FSuspended := OldSuspend;
raise;
end;
end;
procedure TThread.Resume;
var
SuspendCount: Integer;
begin
SuspendCount := ResumeThread(FHandle);
CheckThreadError(SuspendCount >= 0);
if SuspendCount = 1 then
FSuspended := False;
end;
procedure TThread.Terminate;
begin
FTerminated := True;
end;
function TThread.WaitFor: LongWord;
var
WaitResult: Cardinal;
Msg: TMsg;
begin
if GetCurrentThreadID = MainThreadID then
begin
WaitResult := 0;
repeat
if WaitResult = WAIT_OBJECT_0 + 2 then
PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);
WaitResult := MsgWaitForMultipleObjects(1, FHandle, False, 1000, QS_SENDMESSAGE);
CheckThreadError(WaitResult <> WAIT_FAILED);
until WaitResult = WAIT_OBJECT_0;
end else WaitForSingleObject(FHandle, INFINITE);
CheckThreadError(GetExitCodeThread(FHandle, Result));
end;
{ TServiceThread }
procedure TServiceThread.Finalize;
begin
end;
procedure TServiceThread.Initialize;
begin
end;
procedure TServiceThread.Execute;
var
State: Integer;
begin
Initialize;
try
while not FTerminated do
begin
State := GetState;
if not FTerminated then
Service(State);
end;
finally
Finalize;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -