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

📄 mmthread.pas

📁 一套及时通讯的原码
💻 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 + -