📄 mmthread.pas
字号:
{========================================================================}
{= (c) 1995-98 SwiftSoft Ronald Dittrich =}
{========================================================================}
{= All Rights Reserved =}
{========================================================================}
{= D 01099 Dresden = Fax.: +49(0)351-8037944 =}
{= Loewenstr.7a = info@swiftsoft.de =}
{========================================================================}
{= Actual versions on http://www.swiftsoft.de/index.html =}
{========================================================================}
{= This code is for reference purposes only and may not be copied or =}
{= distributed in any format electronic or otherwise except one copy =}
{= for backup purposes. =}
{= =}
{= No Delphi Component Kit or Component individually or in a collection=}
{= subclassed or otherwise from the code in this unit, or associated =}
{= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
{= without express permission from SwiftSoft. =}
{= =}
{= For more licence informations please refer to the associated =}
{= HelpFile. =}
{========================================================================}
{= $Date: 05.10.98 - 18:49:02 $ =}
{========================================================================}
unit MMThread;
{$I COMPILER.INC}
{$C FIXED PRELOAD PERMANENT}
{.$DEFINE _MMDEBUG}
interface
Uses
Windows,
Forms,
Classes,
SysUtils,
MMObj,
MMString,
MMUtils
{$IFDEF _MMDEBUG}
,MMDebug
{$ENDIF}
;
type
EMMThreadError = class(Exception);
TMMThread = class;
{-- TMMRealThread --------------------------------------------------}
TMMRealThread = class(TMMThreadEx)
private
MMThread: TMMThread;
Terminating: Boolean;
procedure Execute; override;
end;
{-- TMLThread ------------------------------------------------------}
TMMThread = class(TMMNonVisualComponent)
private
FThread : TMMRealThread;
FGeneralEvent : THandle;
FThreadCreated : Boolean;
FPriority : TThreadPriority;
FEnabled : Boolean;
FSynchronize : Boolean;
FAutoExecute : Boolean;
FMainThreadWaiting: Boolean;
FWaitForTerminate : Boolean;
FOnStart : TNotifyEvent;
FOnTerminate : TNotifyEvent;
FOnThread : TNotifyEvent;
procedure SetPriority(aValue: TThreadPriority);
procedure SetEnabled(aValue: Boolean);
procedure SetAutoExecute(aValue: Boolean);
function GetHandle: THandle;
function GetThreadID: THandle;
function GetTerminating: Boolean;
function GetTerminated: Boolean;
procedure DoThread;
protected
procedure ChangeDesigning(aValue: Boolean); override;
procedure Loaded; override;
procedure Thread; virtual;
public
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
procedure Execute; virtual;
procedure Terminate; virtual;
procedure SynchronizeVCL(VCLProc: TThreadMethod);
property Handle: THandle read GetHandle;
property ThreadID: THandle read GetThreadID;
property Terminating: Boolean read GetTerminating;
property Terminated: Boolean read GetTerminated;
published
{ Events }
property OnStart: TNotifyEvent read FOnStart write FOnStart;
property OnThread: TNotifyEvent read FOnThread write FOnThread;
property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
property AutoExecute: Boolean read FAutoExecute write SetAutoExecute default False;
property Enabled: Boolean read FEnabled write SetEnabled default True;
property Priority: TThreadPriority read FPriority write SetPriority default tpNormal;
property Synchronize: Boolean read FSynchronize write FSynchronize default True;
property WaitForTerminate: Boolean read FWaitForTerminate write FWaitForTerminate default False;
end;
implementation
{== TMMRealThread ======================================================}
procedure TMMRealThread.Execute;
var
H: THandle;
begin
if (MMThread <> nil) then
try
Priority := MMThread.FPriority;
{ Ready to go, set the general event }
SetEvent(MMThread.FGeneralEvent);
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'ThreadProc started...');
{$ENDIF}
while not Terminated and (MMThread <> nil) do
begin
if not Terminating then MMThread.DoThread;
end;
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'Leave ThreadProc...');
{$ENDIF}
if (MMThread <> nil) then
begin
h := MMThread.FGeneralEvent;
MMThread.FThread := nil;
MMThread := nil;
SetEvent(h);
end;
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'Ready for done...');
{$ENDIF}
except
Application.HandleException(Self);
end;
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'ThreadProc terminated...');
{$ENDIF}
end;
{== TMMThread ==========================================================}
constructor TMMThread.Create(aOwner:TComponent);
begin
inherited Create(aOwner);
FPriority := tpNormal;
FAutoExecute := False;
FEnabled := True;
FSynchronize := True;
FWaitForTerminate := False;
FMainThreadWaiting := False;
ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
end;
{-- TMMThread ----------------------------------------------------------}
destructor TMMThread.Destroy;
begin
if FThreadCreated then
begin
{ Don't run event if form is being destroyed ! }
OnTerminate := Nil;
OnThread := Nil;
Terminate;
end;
inherited Destroy;
end;
{-- TMMThread ----------------------------------------------------------}
procedure TMMThread.ChangeDesigning(aValue: Boolean);
begin
inherited;
if not (csDesigning in ComponentState) then
begin
if AutoExecute and not FThreadCreated then Execute;
end;
end;
{-- TMMThread ----------------------------------------------------------}
procedure TMMThread.Loaded;
begin
inherited Loaded;
if FAutoExecute then Execute;
end;
{-- TMMThread ----------------------------------------------------------}
procedure TMMThread.Execute;
begin
if not (csDesigning in ComponentState) and
not (csLoading in ComponentState) then
begin
if assigned(FOnThread) and not FThreadCreated then
begin
{$IFDEF TRIAL}
{$DEFINE _HACK1}
{$I MMHACK.INC}
{$ENDIF}
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'Try to start Thread...');
{$ENDIF}
FGeneralEvent := CreateEvent(nil, False, False, nil);
FThread := TMMRealThread.Create(True);
if (FThread = nil) then
raise EMMThreadError.Create('Thread:'#10#13+LoadResStr(IDS_THREADERROR));
FThread.MMThread := Self;
FThread.FreeOnTerminate := True;
FThread.Terminating := False;
FThreadCreated := True;
if FEnabled then
begin
FThread.Resume;
{ Wait for it to start... }
if WaitForSingleObject(FGeneralEvent, 1000) <> WAIT_OBJECT_0 then
raise EMMThreadError.Create('Thread:'#10#13+LoadResStr(IDS_THREADERROR));
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'Thread started...');
{$ENDIF}
end;
if Assigned(FOnStart) then FOnStart(self);
end;
end;
end;
{-- TMMThread ----------------------------------------------------------}
procedure TMMThread.Terminate;
begin
if FThreadCreated then
begin
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'Shot down Thread...');
{$ENDIF}
FThread.Terminating := True;
{ in case it is suspended remove all before terminate }
while FThread.Suspended do FThread.Resume;
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'Terminate Thread...');
{$ENDIF}
FThread.Terminate;
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'Start Waiting...');
{$ENDIF}
{ ...and wait for it to die }
if FWaitForTerminate and not FMainThreadWaiting then
WaitForSingleObject(FGeneralEvent, 5000);
if (FThread <> nil) then
FThread.MMThread := nil;
{ free the event }
CloseHandle(FGeneralEvent);
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'Call OnTerminate...');
{$ENDIF}
if Assigned(FOnTerminate) then FOnTerminate(Self);
FThreadCreated := False;
{$IFDEF _MMDEBUG}
DB_WriteStrLn(0,'Thread now stopped...');
{$ENDIF}
end;
end;
{-- TMMThread ----------------------------------------------------------}
function TMMThread.GetTerminating: Boolean;
begin
Result := (FThread = nil) or FThread.Terminating;
end;
{-- TMMThread ----------------------------------------------------------}
function TMMThread.GetTerminated: Boolean;
begin
Result := not FThreadCreated;
end;
{-- TMMThread ----------------------------------------------------------}
procedure TMMThread.SetAutoExecute(aValue: Boolean);
begin
if (aValue <> FAutoExecute) then
begin
FAutoExecute := aValue;
if FAutoExecute then Execute;
end;
{$IFDEF TRIAL}
{$DEFINE _HACK2}
{$I MMHACK.INC}
{$ENDIF}
end;
{-- TMMThread ----------------------------------------------------------}
procedure TMMThread.SetEnabled(aValue:Boolean);
begin
if (aValue <> FEnabled) then
begin
FEnabled := aValue;
if FThreadCreated then FThread.Suspended := not FEnabled;
end;
end;
{-- TMMThread ----------------------------------------------------------}
procedure TMMThread.SetPriority(aValue: TThreadPriority);
begin
if (aValue <> FPriority) then
begin
FPriority := aValue;
if FThreadCreated then FThread.Priority := FPriority;
end;
{$IFDEF TRIAL}
{$DEFINE _HACK3}
{$I MMHACK.INC}
{$ENDIF}
end;
{-- TMMThread ----------------------------------------------------------}
procedure TMMThread.SynchronizeVCL(VCLProc: TThreadMethod);
begin
if FThreadCreated then
begin
FMainThreadWaiting := True;
FThread.Synchronize(VCLProc);
FMainThreadWaiting := False;
end;
end;
{-- TMMThread ----------------------------------------------------------}
procedure TMMThread.DoThread;
begin
if FEnabled then
begin
if FSynchronize then
SynchronizeVCL(Thread)
else
Thread;
end;
end;
{-- TMMThread ----------------------------------------------------------}
procedure TMMThread.Thread;
begin
if assigned(FOnThread) then FOnThread(Self);
end;
{-- TMMThread ----------------------------------------------------------}
function TMMThread.GetHandle : THandle;
begin
Result := 0;
if FThreadCreated then Result := FThread.Handle;
end;
{-- TMMThread ----------------------------------------------------------}
function TMMThread.GetThreadID: THandle;
begin
Result := 0;
if FThreadCreated then Result := FThread.ThreadId;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -