MMThread.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:12k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49(0)351-8037944               =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/index.html               =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 05.10.98 - 18:49:02 $                                        =}
  24. {========================================================================}
  25. unit MMThread;
  26. {$I COMPILER.INC}
  27. {$C FIXED PRELOAD PERMANENT}
  28. {.$DEFINE _MMDEBUG}
  29. interface
  30. Uses
  31.     Windows,
  32.     Forms,
  33.     Classes,
  34.     SysUtils,
  35.     MMObj,
  36.     MMString,
  37.     MMUtils
  38.     {$IFDEF _MMDEBUG}
  39.     ,MMDebug
  40.     {$ENDIF}
  41.     ;
  42. type
  43.     EMMThreadError = class(Exception);
  44.     TMMThread      = class;
  45.     {-- TMMRealThread --------------------------------------------------}
  46.     TMMRealThread  = class(TMMThreadEx)
  47.     private
  48.        MMThread: TMMThread;
  49.        Terminating: Boolean;
  50.        procedure Execute; override;
  51.     end;
  52.     {-- TMLThread ------------------------------------------------------}
  53.     TMMThread = class(TMMNonVisualComponent)
  54.     private
  55.       FThread           : TMMRealThread;
  56.       FGeneralEvent     : THandle;
  57.       FThreadCreated    : Boolean;
  58.       FPriority         : TThreadPriority;
  59.       FEnabled          : Boolean;
  60.       FSynchronize      : Boolean;
  61.       FAutoExecute      : Boolean;
  62.       FMainThreadWaiting: Boolean;
  63.       FWaitForTerminate : Boolean;
  64.       FOnStart          : TNotifyEvent;
  65.       FOnTerminate      : TNotifyEvent;
  66.       FOnThread         : TNotifyEvent;
  67.       procedure SetPriority(aValue: TThreadPriority);
  68.       procedure SetEnabled(aValue: Boolean);
  69.       procedure SetAutoExecute(aValue: Boolean);
  70.       function  GetHandle: THandle;
  71.       function  GetThreadID: THandle;
  72.       function  GetTerminating: Boolean;
  73.       function  GetTerminated: Boolean;
  74.       procedure DoThread;
  75.     protected
  76.       procedure ChangeDesigning(aValue: Boolean); override;
  77.       procedure Loaded; override;
  78.       procedure Thread; virtual;
  79.     public
  80.       constructor Create(AOwner : TComponent); override;
  81.       destructor  Destroy; override;
  82.       procedure Execute; virtual;
  83.       procedure Terminate; virtual;
  84.       procedure SynchronizeVCL(VCLProc: TThreadMethod);
  85.       property  Handle: THandle read GetHandle;
  86.       property  ThreadID: THandle read GetThreadID;
  87.       property  Terminating: Boolean read GetTerminating;
  88.       property  Terminated: Boolean read GetTerminated;
  89.     published
  90.       { Events }
  91.       property OnStart: TNotifyEvent read FOnStart write FOnStart;
  92.       property OnThread: TNotifyEvent read FOnThread write FOnThread;
  93.       property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
  94.       property AutoExecute: Boolean read FAutoExecute write SetAutoExecute default False;
  95.       property Enabled: Boolean read FEnabled write SetEnabled default True;
  96.       property Priority: TThreadPriority read FPriority write SetPriority default tpNormal;
  97.       property Synchronize: Boolean read FSynchronize write FSynchronize default True;
  98.       property WaitForTerminate: Boolean read FWaitForTerminate write FWaitForTerminate default False;
  99.   end;
  100. implementation
  101. {== TMMRealThread ======================================================}
  102. procedure TMMRealThread.Execute;
  103. var
  104.    H: THandle;
  105. begin
  106.    if (MMThread <> nil) then
  107.    try
  108.       Priority := MMThread.FPriority;
  109.       { Ready to go, set the general event }
  110.       SetEvent(MMThread.FGeneralEvent);
  111.       {$IFDEF _MMDEBUG}
  112.       DB_WriteStrLn(0,'ThreadProc started...');
  113.       {$ENDIF}
  114.       while not Terminated and (MMThread <> nil) do
  115.       begin
  116.          if not Terminating then MMThread.DoThread;
  117.       end;
  118.       {$IFDEF _MMDEBUG}
  119.       DB_WriteStrLn(0,'Leave ThreadProc...');
  120.       {$ENDIF}
  121.       if (MMThread <> nil) then
  122.       begin
  123.          h := MMThread.FGeneralEvent;
  124.          MMThread.FThread := nil;
  125.          MMThread := nil;
  126.          SetEvent(h);
  127.       end;
  128.       {$IFDEF _MMDEBUG}
  129.       DB_WriteStrLn(0,'Ready for done...');
  130.       {$ENDIF}
  131.    except
  132.       Application.HandleException(Self);
  133.    end;
  134.    {$IFDEF _MMDEBUG}
  135.    DB_WriteStrLn(0,'ThreadProc terminated...');
  136.    {$ENDIF}
  137. end;
  138. {== TMMThread ==========================================================}
  139. constructor TMMThread.Create(aOwner:TComponent);
  140. begin
  141.    inherited Create(aOwner);
  142.    FPriority          := tpNormal;
  143.    FAutoExecute       := False;
  144.    FEnabled           := True;
  145.    FSynchronize       := True;
  146.    FWaitForTerminate  := False;
  147.    FMainThreadWaiting := False;
  148.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  149.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  150. end;
  151. {-- TMMThread ----------------------------------------------------------}
  152. destructor TMMThread.Destroy;
  153. begin
  154.    if FThreadCreated then
  155.    begin
  156.       { Don't run event if form is being destroyed ! }
  157.       OnTerminate := Nil;
  158.       OnThread := Nil;
  159.       Terminate;
  160.    end;
  161.    inherited Destroy;
  162. end;
  163. {-- TMMThread ----------------------------------------------------------}
  164. procedure TMMThread.ChangeDesigning(aValue: Boolean);
  165. begin
  166.    inherited;
  167.    if not (csDesigning in ComponentState) then
  168.    begin
  169.       if AutoExecute and not FThreadCreated then Execute;
  170.    end;
  171. end;
  172. {-- TMMThread ----------------------------------------------------------}
  173. procedure TMMThread.Loaded;
  174. begin
  175.    inherited Loaded;
  176.    if FAutoExecute then Execute;
  177. end;
  178. {-- TMMThread ----------------------------------------------------------}
  179. procedure TMMThread.Execute;
  180. begin
  181.    if not (csDesigning in ComponentState) and
  182.       not (csLoading in ComponentState) then
  183.    begin
  184.       if assigned(FOnThread) and not FThreadCreated then
  185.       begin
  186.          {$IFDEF TRIAL}
  187.          {$DEFINE _HACK1}
  188.          {$I MMHACK.INC}
  189.          {$ENDIF}
  190.          {$IFDEF _MMDEBUG}
  191.          DB_WriteStrLn(0,'Try to start Thread...');
  192.          {$ENDIF}
  193.          FGeneralEvent := CreateEvent(nil, False, False, nil);
  194.          FThread := TMMRealThread.Create(True);
  195.          if (FThread = nil) then
  196.              raise EMMThreadError.Create('Thread:'#10#13+LoadResStr(IDS_THREADERROR));
  197.          FThread.MMThread := Self;
  198.          FThread.FreeOnTerminate := True;
  199.          FThread.Terminating := False;
  200.          FThreadCreated := True;
  201.          if FEnabled then
  202.          begin
  203.             FThread.Resume;
  204.             { Wait for it to start... }
  205.             if WaitForSingleObject(FGeneralEvent, 1000) <> WAIT_OBJECT_0 then
  206.                raise EMMThreadError.Create('Thread:'#10#13+LoadResStr(IDS_THREADERROR));
  207.             {$IFDEF _MMDEBUG}
  208.             DB_WriteStrLn(0,'Thread started...');
  209.             {$ENDIF}
  210.          end;
  211.          if Assigned(FOnStart) then FOnStart(self);
  212.       end;
  213.    end;
  214. end;
  215. {-- TMMThread ----------------------------------------------------------}
  216. procedure TMMThread.Terminate;
  217. begin
  218.    if FThreadCreated then
  219.    begin
  220.       {$IFDEF _MMDEBUG}
  221.       DB_WriteStrLn(0,'Shot down Thread...');
  222.       {$ENDIF}
  223.       FThread.Terminating := True;
  224.       { in case it is suspended remove all before terminate }
  225.       while FThread.Suspended do FThread.Resume;
  226.       {$IFDEF _MMDEBUG}
  227.       DB_WriteStrLn(0,'Terminate Thread...');
  228.       {$ENDIF}
  229.       FThread.Terminate;
  230.       {$IFDEF _MMDEBUG}
  231.       DB_WriteStrLn(0,'Start Waiting...');
  232.       {$ENDIF}
  233.       { ...and wait for it to die }
  234.       if FWaitForTerminate and not FMainThreadWaiting then
  235.          WaitForSingleObject(FGeneralEvent, 5000);
  236.       if (FThread <> nil) then
  237.           FThread.MMThread := nil;
  238.       { free the event }
  239.       CloseHandle(FGeneralEvent);
  240.       {$IFDEF _MMDEBUG}
  241.       DB_WriteStrLn(0,'Call OnTerminate...');
  242.       {$ENDIF}
  243.       if Assigned(FOnTerminate) then FOnTerminate(Self);
  244.       FThreadCreated := False;
  245.       {$IFDEF _MMDEBUG}
  246.       DB_WriteStrLn(0,'Thread now stopped...');
  247.       {$ENDIF}
  248.    end;
  249. end;
  250. {-- TMMThread ----------------------------------------------------------}
  251. function TMMThread.GetTerminating: Boolean;
  252. begin
  253.    Result := (FThread = nil) or FThread.Terminating;
  254. end;
  255. {-- TMMThread ----------------------------------------------------------}
  256. function TMMThread.GetTerminated: Boolean;
  257. begin
  258.    Result := not FThreadCreated;
  259. end;
  260. {-- TMMThread ----------------------------------------------------------}
  261. procedure TMMThread.SetAutoExecute(aValue: Boolean);
  262. begin
  263.    if (aValue <> FAutoExecute) then
  264.    begin
  265.       FAutoExecute := aValue;
  266.       if FAutoExecute then Execute;
  267.    end;
  268.    {$IFDEF TRIAL}
  269.    {$DEFINE _HACK2}
  270.    {$I MMHACK.INC}
  271.    {$ENDIF}
  272. end;
  273. {-- TMMThread ----------------------------------------------------------}
  274. procedure TMMThread.SetEnabled(aValue:Boolean);
  275. begin
  276.    if (aValue <> FEnabled) then
  277.    begin
  278.       FEnabled := aValue;
  279.       if FThreadCreated then FThread.Suspended := not FEnabled;
  280.    end;
  281. end;
  282. {-- TMMThread ----------------------------------------------------------}
  283. procedure TMMThread.SetPriority(aValue: TThreadPriority);
  284. begin
  285.    if (aValue <> FPriority) then
  286.    begin
  287.       FPriority := aValue;
  288.       if FThreadCreated then FThread.Priority := FPriority;
  289.    end;
  290.    {$IFDEF TRIAL}
  291.    {$DEFINE _HACK3}
  292.    {$I MMHACK.INC}
  293.    {$ENDIF}
  294. end;
  295. {-- TMMThread ----------------------------------------------------------}
  296. procedure TMMThread.SynchronizeVCL(VCLProc: TThreadMethod);
  297. begin
  298.    if FThreadCreated then
  299.    begin
  300.       FMainThreadWaiting := True;
  301.       FThread.Synchronize(VCLProc);
  302.       FMainThreadWaiting := False;
  303.    end;
  304. end;
  305. {-- TMMThread ----------------------------------------------------------}
  306. procedure TMMThread.DoThread;
  307. begin
  308.    if FEnabled then
  309.    begin
  310.       if FSynchronize then
  311.          SynchronizeVCL(Thread)
  312.       else
  313.          Thread;
  314.    end;
  315. end;
  316. {-- TMMThread ----------------------------------------------------------}
  317. procedure TMMThread.Thread;
  318. begin
  319.    if assigned(FOnThread) then FOnThread(Self);
  320. end;
  321. {-- TMMThread ----------------------------------------------------------}
  322. function TMMThread.GetHandle : THandle;
  323. begin
  324.    Result := 0;
  325.    if FThreadCreated then Result := FThread.Handle;
  326. end;
  327. {-- TMMThread ----------------------------------------------------------}
  328. function TMMThread.GetThreadID: THandle;
  329. begin
  330.    Result := 0;
  331.    if FThreadCreated then Result := FThread.ThreadId;
  332. end;
  333. end.