Browse Source

增加BMDThread控件代码

Jimi Zhang 3 năm trước cách đây
mục cha
commit
45a12b1779

BIN
Components/BMDThread/Bin/BMThreadDsnD7.bpl


BIN
Components/BMDThread/Bin/BMThreadPkgD7.bpl


BIN
Components/BMDThread/Source/BMDThread.DCR


+ 790 - 0
Components/BMDThread/Source/BMDThread.pas

@@ -0,0 +1,790 @@
+{*> Ver: V1.4 *********      History      ***************************\
+
+Beta V1.0b0		04/29/1999		Released
+Beta V1.0b1		05/24/1999		The Synchro method editors have been added.
+Beta V1.0b2		08/01/2001		Some modifications by Walter Campelo.
+Beta V1.0b3		08/03/2001		Ported to Delphi 6 Restricted group connection to itself.
+Beta V1.0b4		08/11/2001		Bug in supporting subgroups fixed.
+Beta V1.1b0		02/22/2001		Delphi 7 support added.
+V1.2		      12/05/2004		Delphi 2005 support added. UpdateEnabled added.
+V1.3		      12/12/2004		OnTerminate bug fixed.
+V1.4		      01/27/2006		Delphi 2006 support added.
+
+Legal issues: Copyright (C) 1999 - 2006 by Boian Mitov
+              mitov@mitov.com
+              www.mitov.com
+              www.openwire.org
+
+              This software is provided 'as-is', without any express or
+              implied warranty.  In no event will the author be held liable
+              for any  damages arising from the use of this software.
+
+              Permission is granted to anyone to use this software for any
+              purpose, including commercial applications, and to alter it
+              and redistribute it freely, subject to the following
+              restrictions:
+
+              1. The origin of this software must not be misrepresented,
+                 you must not claim that you wrote the original software.
+                 If you use this software in a product, an acknowledgment
+                 in the product documentation would be appreciated but is
+                 not required.
+
+              2. Altered source versions must be plainly marked as such, and
+                 must not be misrepresented as being the original software.
+
+              3. This notice may not be removed or altered from any source
+                 distribution.
+
+\***************************************************************************}
+unit BMDThread;
+
+interface
+
+uses
+  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
+  Syncobjs, ExtCtrls;
+
+type
+  { Forward class declarations }
+  TBMDThread = class;
+  TBMDExecuteThread = class;
+  TBMDThreadGroup = class;
+
+  { Thread events }
+  TBMDThreadNotifyEvent = procedure(Sender: TObject; Thread: TBMDExecuteThread) of object;
+  TBMDThreadDataNotifyEvent = procedure(Sender: TObject; Thread: TBMDExecuteThread; var Data: Pointer) of object;
+  TBMDThreadUpdateNotifyEvent = procedure(Sender: TObject; Thread: TBMDExecuteThread; var Data: Pointer; Percent: Integer) of object;
+  TBMDThreadSynchroNotifyEvent = procedure(Sender: TBMDThread; Thread: TBMDExecuteThread) of object;
+  TBMDThreadSynchroDataNotifyEvent = procedure(Sender: TBMDThread; Thread: TBMDExecuteThread; var Data: Pointer) of object;
+
+  { TBMDExecuteThread class }
+  TBMDExecuteThread = class(TThread)
+  private
+    { Private declarations }
+  protected
+    { Protected declarations }
+    ThreadOwner: TBMDThread;
+    FData: Pointer;
+    FNotifyEvent: TNotifyEvent;
+    FThreadNotifyEvent: TBMDThreadSynchroNotifyEvent;
+    FThreadDataNotifyEvent: TBMDThreadSynchroDataNotifyEvent;
+    UpdateData: Pointer;
+    procedure Execute(); override;
+  public
+    { Public declarations }
+    PercentProgress: Integer;
+    constructor Create(AThreadOwner: TBMDThread; AUpdateData: Pointer); virtual;
+    procedure DoNotifySynchro;
+    procedure DoThreadNotifySynchro;
+    procedure DoThreadNotifySynchroData;
+    procedure Synchronize(SynchroEvent: TNotifyEvent); overload;
+    procedure Synchronize(SynchroEvent: TBMDThreadSynchroNotifyEvent); overload;
+    procedure Synchronize(SynchroEvent: TBMDThreadSynchroDataNotifyEvent; Data: Pointer); overload;
+    // The folowing two functions are obsolete and should not be used in future !!!
+    // Obsolete !!! Don't use any more !!! >>>>
+    procedure Synchronize(SynchroEvent: TBMDThreadNotifyEvent); overload;
+    procedure Synchronize(SynchroEvent: TBMDThreadDataNotifyEvent; Data: Pointer); overload;
+    // <<< Obsolete !!! Don't use any more !!!
+    property Terminated;
+  end;
+
+  { TBMDThread class }
+  TBMDThreadBase = class(TComponent)
+  private
+    FOnUpdate: TBMDThreadUpdateNotifyEvent;
+    FOnStart: TBMDThreadDataNotifyEvent;
+    FOnTerminate: TBMDThreadDataNotifyEvent;
+    FThreadGroup: TBMDThreadGroup;
+    FUpdatePriority: Integer;
+  protected
+    UpdateCriticalSection: TCriticalSection;
+    function GetRuning(): Boolean; virtual; abstract;
+    procedure SetThreadGroup(AThreadGroup: TBMDThreadGroup);
+    procedure ReportStarted(ThreadGroup: TBMDThreadGroup); virtual; abstract;
+    procedure ReportTerminated(ThreadGroup: TBMDThreadGroup); virtual; abstract;
+    function  AddMe(AThreadGroup: TBMDThreadGroup) : Boolean; virtual; abstract;
+    procedure RemoveMe(AThreadGroup: TBMDThreadGroup); virtual; abstract;
+  public
+    constructor Create(Owner: TComponent); override;
+    destructor Destroy; override;
+    procedure Start(); overload; virtual; abstract;
+    procedure Start(Data: Pointer); overload; virtual; abstract;
+    procedure Stop(); virtual; abstract;
+    procedure Suspend(); virtual; abstract;
+    procedure Resume(); virtual; abstract;
+    property Runing: Boolean read GetRuning;
+    property ThreadGroup: TBMDThreadGroup read FThreadGroup write SetThreadGroup;
+    property UpdatePriority: Integer read FUpdatePriority write FUpdatePriority default 0;
+    property OnUpdate: TBMDThreadUpdateNotifyEvent read FOnUpdate write FOnUpdate;
+    property OnStart: TBMDThreadDataNotifyEvent read FOnStart write FOnStart;
+    property OnTerminate: TBMDThreadDataNotifyEvent read FOnTerminate write FOnTerminate;
+  end;
+
+  { TBMDThread class }
+  TBMDThread = class(TBMDThreadBase)
+  protected
+    FUpdateTimer: TTimer;
+    FOnExecute: TBMDThreadDataNotifyEvent;
+    FExecuteThread: TBMDExecuteThread;
+    FPriority: TThreadPriority;
+    FUpdateEnabled: Boolean;
+    FInterrupted: Boolean;
+    procedure OnUpdateTimer(Sender: TObject); virtual;
+    procedure Execute(); virtual;
+    procedure OnThreadTerminate(Sender: TObject); virtual;
+    procedure OnThreadTerminateClose(Sender: TObject); virtual;
+    procedure ReportStarted(ThreadGroup: TBMDThreadGroup); override;
+    procedure ReportTerminated(ThreadGroup: TBMDThreadGroup); override;
+    function  AddMe(AThreadGroup: TBMDThreadGroup) : Boolean; override;
+    procedure RemoveMe(AThreadGroup: TBMDThreadGroup); override;
+    procedure SetTimeInterval(TimeInterval: Cardinal);
+    function GetTimeInterval(): Cardinal;
+    procedure SetPriority(Value: TThreadPriority);
+    function GetPriority(): TThreadPriority;
+    function GetRuning(): Boolean; override;
+    function GetEmptyEntry(): TPersistent;
+    procedure SetUpdateEnabled(Value: Boolean);
+  public
+    constructor Create(Owner: TComponent); override;
+    destructor Destroy; override;
+    procedure Start(); overload; override;
+    procedure Start(Data: Pointer); overload; override;
+    procedure Stop(); override;
+    procedure Suspend(); override;
+    procedure Resume(); override;
+    property Runing;
+    property Interrupted: Boolean read FInterrupted;
+    property Thread: TBMDExecuteThread read FExecuteThread;
+  published
+    property RefreshInterval: Cardinal read GetTimeInterval write SetTimeInterval default 100;
+    property Priority: TThreadPriority read GetPriority write SetPriority default tpNormal;
+    property ThreadGroup;
+    property UpdatePriority;
+    property UpdateEnabled : Boolean read FUpdateEnabled write SetUpdateEnabled; 
+    property SynchroMethods: TPersistent read GetEmptyEntry;
+    property OnExecute: TBMDThreadDataNotifyEvent read FOnExecute write FOnExecute;
+    property OnUpdate;
+    property OnStart;
+    property OnTerminate;
+  end;
+
+  TBMDThreadGroup = class(TBMDThreadBase)
+  protected
+    ThreadItemsList: TList;
+    ThreadsList: TList;
+    FOnThreadUpdate: TBMDThreadUpdateNotifyEvent;
+    FOnThreadStart: TBMDThreadDataNotifyEvent;
+    FOnThreadTerminate: TBMDThreadDataNotifyEvent;
+    // Protected by CriticalSection
+    FCountRuning: Integer;
+    function GetRuning(): Boolean; override;
+    function GetCountRuning(): Integer; virtual;
+    function GetThreadItemsCount(): Integer;
+    function GetThreadItems(Index: Integer): TBMDThreadBase;
+    function GetThreadsCount(): Integer;
+    function GetThreads(Index: Integer): TBMDThread;
+    procedure ReportStarted(ThreadGroup: TBMDThreadGroup); override;
+    procedure ReportTerminated(ThreadGroup: TBMDThreadGroup); override;
+    function  AddMe(AThreadGroup: TBMDThreadGroup) : Boolean; override;
+    procedure RemoveMe(AThreadGroup: TBMDThreadGroup); override;
+    function LinkedToMe( ThreadBase : TBMDThreadBase ) : Boolean;
+  public
+    constructor Create(Owner: TComponent); override;
+    destructor Destroy; override;
+    procedure Start(); overload; override;
+    procedure Start(Data: Pointer); overload; override;
+    procedure Stop(); override;
+    procedure Suspend(); override;
+    procedure Resume(); override;
+    function  AddThread(AThread: TBMDThread) : Boolean;
+    procedure RemoveThread(AThread: TBMDThread);
+    function  AddThreadGroup(AThreadGroup: TBMDThreadGroup) : Boolean;
+    procedure RemoveThreadGroup(AThreadGroup: TBMDThreadGroup);
+    procedure ThreadStarted(Sender: TObject; Thread: TBMDExecuteThread; var Data: Pointer);
+    procedure ThreadUpdate(Sender: TObject; Thread: TBMDExecuteThread; var Data: Pointer; AUpdatePriority: Integer; PercentProgres: Integer);
+    procedure ThreadTerminated(Sender: TObject; Thread: TBMDExecuteThread; var Data: Pointer);
+    
+  public
+    property Runing;
+    property CountRuning: Integer read GetCountRuning;
+    property ThreadItemsCount: Integer read GetThreadItemsCount;
+    property ThreadItems[Index: Integer]: TBMDThreadBase read GetThreadItems;
+    property ThreadsCount: Integer read GetThreadsCount;
+    property Threads[Index: Integer]: TBMDThread read GetThreads;
+
+  published
+    property ThreadGroup;
+    property UpdatePriority;
+    property OnUpdate;
+    property OnStart;
+    property OnTerminate;
+    property OnThreadUpdate: TBMDThreadUpdateNotifyEvent read FOnThreadUpdate write FOnThreadUpdate;
+    property OnThreadStart: TBMDThreadDataNotifyEvent read FOnThreadStart write FOnThreadStart;
+    property OnThreadTerminate: TBMDThreadDataNotifyEvent read FOnThreadTerminate write FOnThreadTerminate;
+  end;
+
+implementation
+
+{ TBMDExecuteThread }
+
+constructor TBMDExecuteThread.Create(AThreadOwner: TBMDThread; AUpdateData: Pointer);
+begin
+  inherited Create(True);
+  ThreadOwner := AThreadOwner;
+  UpdateData := AUpdateData;
+  OnTerminate := ThreadOwner.OnThreadTerminate;
+  FreeOnTerminate := True;
+  Priority := ThreadOwner.FPriority;
+  PercentProgress := 0;
+end;
+
+procedure TBMDExecuteThread.DoNotifySynchro;
+begin
+  if (Assigned(FNotifyEvent)) then
+    FNotifyEvent(ThreadOwner);
+end;
+
+procedure TBMDExecuteThread.DoThreadNotifySynchro;
+begin
+  if (Assigned(FThreadNotifyEvent)) then
+    FThreadNotifyEvent(ThreadOwner, Self);
+end;
+
+procedure TBMDExecuteThread.DoThreadNotifySynchroData;
+begin
+  if (Assigned(FThreadDataNotifyEvent)) then
+    FThreadDataNotifyEvent(ThreadOwner, Self, FData);
+end;
+
+procedure TBMDExecuteThread.Synchronize(SynchroEvent: TNotifyEvent);
+begin
+  if (Terminated) then
+    Exit;
+  if (not Assigned(SynchroEvent)) then
+    Exit;
+  FNotifyEvent := SynchroEvent;
+  inherited Synchronize(DoNotifySynchro);
+end;
+
+procedure TBMDExecuteThread.Synchronize(SynchroEvent: TBMDThreadSynchroNotifyEvent);
+begin
+  if (Terminated) then
+    Exit;
+  if (not Assigned(SynchroEvent)) then
+    Exit;
+  FThreadNotifyEvent := SynchroEvent;
+  inherited Synchronize(DoThreadNotifySynchro);
+end;
+
+//---------------------------------------------------------------------------
+// The folowing two functions are obsolete and should not be used in future !!!
+// <<< Obsolete !!! Don't use any more !!!
+
+procedure TBMDExecuteThread.Synchronize(SynchroEvent: TBMDThreadNotifyEvent);
+begin
+  Synchronize(TBMDThreadSynchroNotifyEvent(SynchroEvent));
+end;
+
+procedure TBMDExecuteThread.Synchronize(SynchroEvent: TBMDThreadDataNotifyEvent; Data: Pointer);
+begin
+  Synchronize(TBMDThreadSynchroDataNotifyEvent(SynchroEvent), Data);
+end;
+// End of Obsolete !!! Don't use any more !!! >>>>
+
+procedure TBMDExecuteThread.Synchronize(SynchroEvent: TBMDThreadSynchroDataNotifyEvent; Data: Pointer);
+begin
+  if (Terminated) then
+    Exit;
+  if (not Assigned(SynchroEvent)) then
+    Exit;
+  FThreadDataNotifyEvent := SynchroEvent;
+  FData := Data;
+  inherited Synchronize(DoThreadNotifySynchroData);
+end;
+
+procedure TBMDExecuteThread.Execute();
+begin
+  ThreadOwner.Execute();
+end;
+
+{ TBMDThreadBase }
+
+constructor TBMDThreadBase.Create(Owner: TComponent);
+begin
+  inherited;
+  FUpdatePriority := 0;
+  FThreadGroup := nil;
+  UpdateCriticalSection := TCriticalSection.Create;
+end;
+
+destructor TBMDThreadBase.Destroy;
+begin
+  SetThreadGroup(nil);
+  UpdateCriticalSection.Free;
+  inherited;
+end;
+
+procedure TBMDThreadBase.SetThreadGroup(AThreadGroup: TBMDThreadGroup);
+begin
+  if (AThreadGroup = FThreadGroup) then
+    Exit;
+  if (FThreadGroup <> nil) then
+    RemoveMe(FThreadGroup);
+
+  FThreadGroup := nil;
+  if (AThreadGroup <> nil) then
+    begin
+    if( AddMe(AThreadGroup)) then
+      FThreadGroup := AThreadGroup;
+      
+    end;
+
+end;
+
+{ TBMDThread }
+
+constructor TBMDThread.Create(Owner: TComponent);
+begin
+  inherited;
+  FExecuteThread := nil;
+  FPriority := tpNormal;
+  FUpdateTimer := TTimer.Create(Self);
+  FUpdateTimer.Enabled := False;
+  FUpdateTimer.OnTimer := OnUpdateTimer;
+  FUpdateTimer.Interval := 100;
+end;
+
+destructor TBMDThread.Destroy;
+begin
+  FUpdateTimer.Enabled := False;
+  if (FExecuteThread <> nil) then
+  begin
+    FExecuteThread.OnTerminate := OnThreadTerminateClose;
+    FExecuteThread.Terminate();
+    while (FExecuteThread <> nil) do
+      Application.ProcessMessages();
+    //    FExecuteThread = NIL;
+  end;
+  FUpdateTimer.Free;
+  inherited;
+end;
+
+procedure TBMDThread.OnUpdateTimer(Sender: TObject);
+begin
+  if (FExecuteThread = nil) then
+    Exit;
+  if (ThreadGroup <> nil) then
+    ThreadGroup.ThreadUpdate(Self, FExecuteThread, FExecuteThread.UpdateData, UpdatePriority, FExecuteThread.PercentProgress);
+  if (Assigned(OnUpdate)) then
+  begin
+    UpdateCriticalSection.Enter();
+    OnUpdate(Self, FExecuteThread, FExecuteThread.UpdateData, FExecuteThread.PercentProgress);
+    UpdateCriticalSection.Leave();
+  end;
+end;
+
+procedure TBMDThread.Execute();
+begin
+  if (Assigned(OnExecute)) then
+    OnExecute(Self, FExecuteThread, FExecuteThread.UpdateData);
+  FInterrupted := FExecuteThread.Terminated;
+end;
+
+procedure TBMDThread.OnThreadTerminate(Sender: TObject);
+begin
+  FUpdateTimer.Enabled := False;
+//  FExecuteThread.Resume();
+  FExecuteThread := nil;
+  ReportTerminated(ThreadGroup);
+  if (Assigned(OnTerminate)) then
+  begin
+    UpdateCriticalSection.Enter();
+    OnTerminate(Self, Sender as TBMDExecuteThread, (Sender as TBMDExecuteThread).UpdateData);
+    UpdateCriticalSection.Leave();
+  end;
+  FUpdateTimer.Enabled := FUpdateEnabled;
+end;
+
+procedure TBMDThread.OnThreadTerminateClose(Sender: TObject);
+begin
+  FExecuteThread := nil;
+end;
+
+procedure TBMDThread.ReportStarted(ThreadGroup: TBMDThreadGroup);
+begin
+  if (Runing) then
+    if (ThreadGroup <> nil) then
+      ThreadGroup.ThreadStarted(Self, FExecuteThread, FExecuteThread.UpdateData);
+end;
+
+procedure TBMDThread.ReportTerminated(ThreadGroup: TBMDThreadGroup);
+begin
+  if (not Runing) then
+    if (ThreadGroup <> nil) then
+      ThreadGroup.ThreadTerminated(Self, FExecuteThread, FExecuteThread.UpdateData);
+end;
+
+function TBMDThread.AddMe(AThreadGroup: TBMDThreadGroup) : Boolean;
+begin
+  Result := AThreadGroup.AddThread(Self);
+end;
+
+procedure TBMDThread.RemoveMe(AThreadGroup: TBMDThreadGroup);
+begin
+  AThreadGroup.RemoveThread(Self);
+end;
+
+procedure TBMDThread.Suspend();
+begin
+  if (FExecuteThread <> nil) then
+    FExecuteThread.Suspend();
+end;
+
+procedure TBMDThread.Resume();
+begin
+  if (FExecuteThread <> nil) then
+    FExecuteThread.Resume();
+end;
+
+function TBMDThread.GetTimeInterval(): Cardinal;
+begin
+  Result := FUpdateTimer.Interval;
+end;
+
+procedure TBMDThread.SetTimeInterval(TimeInterval: Cardinal);
+begin
+  FUpdateTimer.Interval := TimeInterval;
+end;
+
+function TBMDThread.GetRuning(): Boolean;
+begin
+  Result := (FExecuteThread <> nil);
+end;
+
+procedure TBMDThread.SetPriority(Value: TThreadPriority);
+begin
+  FPriority := Value;
+  if (FExecuteThread <> nil) then
+    FExecuteThread.Priority := Value;
+end;
+
+procedure TBMDThread.SetUpdateEnabled(Value: Boolean);
+begin
+  if( Value = FUpdateEnabled ) then
+    Exit;
+
+  FUpdateEnabled := Value;
+  FUpdateTimer.Enabled := Value; 
+end;
+
+function TBMDThread.GetPriority(): TThreadPriority;
+begin
+  Result := FPriority;
+end;
+
+procedure TBMDThread.Start(Data: Pointer);
+begin
+  if (FExecuteThread <> nil) then
+    Exit;
+  FExecuteThread := TBMDExecuteThread.Create(Self, Data);
+  FInterrupted := False;
+  ReportStarted(ThreadGroup);
+  if (Assigned(OnStart)) then
+  begin
+    UpdateCriticalSection.Enter();
+    OnStart(Self, FExecuteThread, FExecuteThread.UpdateData);
+    UpdateCriticalSection.Leave();
+  end;
+  FExecuteThread.Resume();
+  FUpdateTimer.Enabled := FUpdateEnabled;
+end;
+
+procedure TBMDThread.Start();
+begin
+  Start(nil);
+end;
+
+procedure TBMDThread.Stop();
+begin
+  if (FExecuteThread <> nil) then
+  begin
+    FExecuteThread.Resume();
+    FExecuteThread.Terminate();
+  end;
+end;
+
+{ TBMDThreadGroup }
+
+constructor TBMDThreadGroup.Create(Owner: TComponent);
+begin
+  inherited;
+  FCountRuning := 0;
+  OnThreadStart := nil;
+  OnThreadTerminate := nil;
+  ThreadItemsList := TList.Create;
+  ThreadsList := TList.Create;
+end;
+
+destructor TBMDThreadGroup.Destroy;
+begin
+  while (ThreadsCount <> 0) do
+    Threads[0].ThreadGroup := nil;
+
+  while (ThreadItemsCount <> 0) do
+    ThreadItems[0].ThreadGroup := nil;
+
+  ThreadsList.Free;
+  ThreadItemsList.Free;
+  inherited;
+end;
+
+function TBMDThreadGroup.GetRuning(): Boolean;
+begin
+  Result := (GetCountRuning() > 0);
+end;
+
+function TBMDThreadGroup.GetCountRuning(): Integer;
+begin
+  UpdateCriticalSection.Enter();
+  Result := FCountRuning;
+  UpdateCriticalSection.Leave();
+end;
+
+procedure TBMDThreadGroup.Suspend();
+var
+  I: Integer;
+begin
+  for I := 0 to ThreadItemsCount - 1 do
+    ThreadItems[I].Suspend();
+end;
+
+procedure TBMDThreadGroup.Resume();
+var
+  I: Integer;
+begin
+  for I := 0 to ThreadItemsCount - 1 do
+    ThreadItems[I].Resume();
+end;
+
+function TBMDThreadGroup.AddMe(AThreadGroup: TBMDThreadGroup) : Boolean;
+begin
+  Result := AThreadGroup.AddThreadGroup(Self);
+end;
+
+procedure TBMDThreadGroup.RemoveMe(AThreadGroup: TBMDThreadGroup);
+begin
+  AThreadGroup.RemoveThreadGroup(Self);
+end;
+
+procedure TBMDThreadGroup.ThreadStarted(Sender: TObject; Thread: TBMDExecuteThread; var Data: Pointer);
+var
+  TmpCountRuning: Integer;
+begin
+  // Protected by CriticalSection
+  UpdateCriticalSection.Enter();
+  TmpCountRuning := FCountRuning;
+  Inc(FCountRuning);
+  if (Assigned(OnThreadStart)) then
+    OnThreadStart(Sender, Thread, Data);
+  UpdateCriticalSection.Leave();
+  // End of Protected by CriticalSection
+  if (ThreadGroup <> nil) then
+    ThreadGroup.ThreadStarted(Sender, Thread, Data);
+  if (TmpCountRuning = 0) then
+  begin
+    if (Assigned(OnStart)) then
+      OnStart(Sender, Thread, Data);
+  end;
+end;
+
+procedure TBMDThreadGroup.ThreadUpdate(Sender: TObject; Thread: TBMDExecuteThread; var Data: Pointer; AUpdatePriority: Integer; PercentProgres: Integer);
+var
+  I: Integer;
+  IntThread: TBMDThreadBase;
+begin
+  if (Assigned(OnThreadUpdate)) then
+    OnThreadUpdate(Sender, Thread, Data, PercentProgres);
+  if (Assigned(OnUpdate)) then
+  begin
+    for I := 0 to ThreadItemsCount - 1 do
+    begin
+      IntThread := ThreadItems[I];
+      if (IntThread.Runing) then
+        if (IntThread.UpdatePriority > AUpdatePriority) then
+          Exit;
+    end;
+    OnUpdate(Sender, Thread, Data, PercentProgres);
+  end;
+end;
+
+function TBMDThreadGroup.GetThreadItemsCount(): Integer;
+begin
+  Result := ThreadItemsList.Count;
+end;
+
+function TBMDThreadGroup.GetThreadItems(Index: Integer): TBMDThreadBase;
+begin
+  Result := TBMDThreadBase(ThreadItemsList.Items[Index]);
+end;
+
+function TBMDThreadGroup.GetThreadsCount(): Integer;
+begin
+  Result := ThreadsList.Count;
+end;
+
+function TBMDThreadGroup.GetThreads(Index: Integer): TBMDThread;
+begin
+  Result := TBMDThread(ThreadsList.Items[Index]);
+end;
+
+procedure TBMDThreadGroup.ThreadTerminated(Sender: TObject; Thread: TBMDExecuteThread; var Data: Pointer);
+var
+  TempCount: Integer;
+begin
+  // Protected by CriticalSection
+  UpdateCriticalSection.Enter();
+  if (FCountRuning <> 0) then
+    Dec(FCountRuning);
+  TempCount := FCountRuning;
+  UpdateCriticalSection.Leave();
+  // End of Protected by CriticalSection
+  if (Assigned(OnThreadTerminate)) then
+    OnThreadTerminate(Sender, Thread, Data);
+  if (ThreadGroup <> nil) then
+    ThreadGroup.ThreadTerminated(Sender, Thread, Data);
+  if (TempCount = 0) then
+  begin
+    if (Assigned(OnTerminate)) then
+      OnTerminate(Sender, Thread, Data);
+  end;
+end;
+
+procedure TBMDThreadGroup.ReportStarted(ThreadGroup: TBMDThreadGroup);
+var
+  I: Integer;
+begin
+  if (ThreadGroup <> nil) then
+    for I := 0 to ThreadItemsCount - 1 do
+      ThreadItems[I].ReportStarted(ThreadGroup);
+end;
+
+procedure TBMDThreadGroup.ReportTerminated(ThreadGroup: TBMDThreadGroup);
+var
+  I: Integer;
+begin
+  if (ThreadGroup <> nil) then
+    for I := 0 to ThreadItemsCount - 1 do
+      ThreadItems[I].ReportTerminated(ThreadGroup);
+end;
+
+procedure TBMDThreadGroup.Start();
+begin
+  Start(nil);
+end;
+
+procedure TBMDThreadGroup.Start(Data: Pointer);
+var
+  I: Integer;
+begin
+  for I := 0 to ThreadItemsCount - 1 do
+    ThreadItems[I].Start(Data);
+end;
+
+procedure TBMDThreadGroup.Stop();
+var
+  I: Integer;
+begin
+  for I := 0 to ThreadItemsCount - 1 do
+    ThreadItems[I].Stop();
+end;
+
+function TBMDThreadGroup.LinkedToMe( ThreadBase : TBMDThreadBase ) : Boolean;
+var
+  AThreadBase : TBMDThreadBase;
+  
+begin
+  AThreadBase := Self;
+  Result := True;
+  while( AThreadBase <> NIL ) do
+    begin
+    if( AThreadBase = ThreadBase ) then
+      Exit;
+
+    AThreadBase := AThreadBase.ThreadGroup;
+    end;
+    
+  Result := False;
+end;
+
+function TBMDThreadGroup.AddThread(AThread: TBMDThread) : Boolean;
+begin
+  Result := False;
+  if( LinkedToMe( AThread )) then
+    Exit;
+
+  if (AThread.Runing) then
+    AThread.ReportStarted(Self);
+  // Protected by CriticalSection
+  UpdateCriticalSection.Enter();
+  ThreadItemsList.Add(AThread);
+  ThreadsList.Add(AThread);
+  UpdateCriticalSection.Leave();
+  // End of Protected by CriticalSection
+  Result := True;
+end;
+
+function TBMDThreadGroup.AddThreadGroup(AThreadGroup: TBMDThreadGroup) : Boolean;
+var
+  I: Integer;
+begin
+  Result := False;
+  if( LinkedToMe( AThreadGroup )) then
+    Exit;
+
+  if (AThreadGroup.Runing) then
+    AThreadGroup.ReportStarted(Self);
+  // Protected by CriticalSection
+  UpdateCriticalSection.Enter();
+  ThreadItemsList.Add(AThreadGroup);
+  for I := 0 to AThreadGroup.ThreadsCount - 1 do
+    ThreadsList.Add(AThreadGroup.Threads[I]);
+  UpdateCriticalSection.Leave();
+  // End of Protected by CriticalSection
+  Result := True;
+end;
+
+procedure TBMDThreadGroup.RemoveThread(AThread: TBMDThread);
+begin
+  if (AThread.Runing) then
+    AThread.ReportTerminated(Self);
+  // Protected by CriticalSection
+  UpdateCriticalSection.Enter();
+  ThreadItemsList.Remove(AThread);
+  ThreadsList.Remove(AThread);
+  UpdateCriticalSection.Leave();
+  // End of Protected by CriticalSection
+end;
+
+procedure TBMDThreadGroup.RemoveThreadGroup(AThreadGroup: TBMDThreadGroup);
+var
+  I: Integer;
+begin
+  if (AThreadGroup.Runing) then
+    AThreadGroup.ReportTerminated(Self);
+  // Protected by CriticalSection
+  UpdateCriticalSection.Enter();
+  ThreadItemsList.Remove(AThreadGroup);
+  for I := 0 to AThreadGroup.ThreadsCount - 1 do
+    ThreadsList.Remove(AThreadGroup.Threads[I]);
+  UpdateCriticalSection.Leave();
+  // End of Protected by CriticalSection
+end;
+
+function TBMDThread.GetEmptyEntry(): TPersistent;
+begin
+  Result := nil;
+end;
+
+end.
+

+ 259 - 0
Components/BMDThread/Source/BMDThreadEditors.dfm

@@ -0,0 +1,259 @@
+object SynchroMethodsForm: TSynchroMethodsForm
+  Left = 307
+  Top = 203
+  Caption = 'Synchro methods'
+  ClientHeight = 311
+  ClientWidth = 412
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'MS Sans Serif'
+  Font.Style = []
+  OldCreateOrder = False
+  OnResize = FormResize
+  OnShow = FormShow
+  PixelsPerInch = 96
+  TextHeight = 13
+  object PageControl: TPageControl
+    Left = 0
+    Top = 0
+    Width = 412
+    Height = 292
+    ActivePage = ThreadSynchroTabSheet
+    Align = alClient
+    TabOrder = 0
+    OnChange = PageControlChange
+    object ThreadSynchroTabSheet: TTabSheet
+      Caption = 'Thread synchro methods'
+      object ThreadEventsListView: TListView
+        Left = 0
+        Top = 0
+        Width = 302
+        Height = 264
+        Align = alClient
+        Columns = <
+          item
+            Caption = 'Name'
+            Width = 120
+          end
+          item
+            Caption = 'Parameters'
+          end>
+        HideSelection = False
+        RowSelect = True
+        TabOrder = 0
+        ViewStyle = vsReport
+        OnChange = ThreadEventsListViewChange
+        OnDblClick = ShowButton1Click
+        OnEdited = ThreadEventsListViewEdited
+        OnKeyPress = ThreadEventsListViewKeyPress
+      end
+      object Panel1: TPanel
+        Left = 302
+        Top = 0
+        Width = 102
+        Height = 264
+        Align = alRight
+        BevelOuter = bvLowered
+        TabOrder = 1
+        object CreateGroupBox: TGroupBox
+          Left = 6
+          Top = 40
+          Width = 89
+          Height = 81
+          Caption = ' Create '
+          TabOrder = 0
+          object BtnNoDataEvent: TBitBtn
+            Left = 8
+            Top = 16
+            Width = 73
+            Height = 25
+            Caption = '&No data'
+            TabOrder = 0
+            OnClick = BtnNoDataEventClick
+          end
+          object BtnDataEvent: TBitBtn
+            Left = 8
+            Top = 48
+            Width = 73
+            Height = 25
+            Caption = 'With &data'
+            TabOrder = 1
+            OnClick = BtnDataEventClick
+          end
+        end
+        object RenameButton1: TBitBtn
+          Left = 14
+          Top = 128
+          Width = 75
+          Height = 25
+          Caption = '&Rename'
+          TabOrder = 1
+          OnClick = RenameButton1Click
+        end
+        object ShowButton1: TBitBtn
+          Left = 14
+          Top = 160
+          Width = 75
+          Height = 25
+          Caption = '&Show'
+          TabOrder = 2
+          OnClick = ShowButton1Click
+        end
+        object Panel3: TPanel
+          Left = 1
+          Top = 188
+          Width = 100
+          Height = 75
+          Align = alBottom
+          BevelOuter = bvNone
+          TabOrder = 3
+          object CopyCallButton1: TBitBtn
+            Left = 14
+            Top = 10
+            Width = 75
+            Height = 25
+            Caption = '&Copy call'
+            TabOrder = 0
+            OnClick = CopyCallButton1Click
+          end
+          object GenCallButton1: TBitBtn
+            Left = 14
+            Top = 42
+            Width = 75
+            Height = 25
+            Caption = '&Paste call'
+            TabOrder = 1
+            OnClick = GenCallButton1Click
+          end
+        end
+        object RefreshButton1: TBitBtn
+          Left = 14
+          Top = 10
+          Width = 75
+          Height = 25
+          Caption = 'Re&fresh'
+          TabOrder = 4
+          OnClick = RefreshButton1Click
+        end
+      end
+    end
+    object TabSheet2: TTabSheet
+      Caption = 'Standard notify events'
+      ExplicitLeft = 0
+      ExplicitTop = 0
+      ExplicitWidth = 0
+      ExplicitHeight = 0
+      object StdEventsListView: TListView
+        Left = 0
+        Top = 0
+        Width = 302
+        Height = 271
+        Align = alClient
+        Columns = <
+          item
+            Caption = 'Name'
+            Width = 120
+          end
+          item
+            Caption = 'Parameters'
+          end>
+        HideSelection = False
+        RowSelect = True
+        TabOrder = 0
+        ViewStyle = vsReport
+        OnChange = ThreadEventsListViewChange
+        OnDblClick = ShowButton1Click
+        OnEdited = ThreadEventsListViewEdited
+        OnKeyPress = ThreadEventsListViewKeyPress
+      end
+      object Panel2: TPanel
+        Left = 302
+        Top = 0
+        Width = 102
+        Height = 264
+        Align = alRight
+        BevelOuter = bvLowered
+        TabOrder = 1
+        object NewStdButton: TBitBtn
+          Left = 14
+          Top = 56
+          Width = 75
+          Height = 25
+          Caption = '&New'
+          TabOrder = 0
+          OnClick = NewStdButtonClick
+        end
+        object RenameButton2: TBitBtn
+          Left = 14
+          Top = 128
+          Width = 75
+          Height = 25
+          Caption = '&Rename'
+          TabOrder = 1
+          OnClick = RenameButton1Click
+        end
+        object ShowButton2: TBitBtn
+          Left = 14
+          Top = 160
+          Width = 75
+          Height = 25
+          Caption = '&Show'
+          TabOrder = 2
+          OnClick = ShowButton1Click
+        end
+        object Panel4: TPanel
+          Left = 1
+          Top = 195
+          Width = 100
+          Height = 75
+          Align = alBottom
+          BevelOuter = bvNone
+          TabOrder = 3
+          object CopyCallButton2: TBitBtn
+            Left = 14
+            Top = 10
+            Width = 75
+            Height = 25
+            Caption = '&Copy call'
+            TabOrder = 0
+            OnClick = CopyCallButton1Click
+          end
+          object GenCallButton2: TBitBtn
+            Left = 14
+            Top = 42
+            Width = 75
+            Height = 25
+            Caption = '&Paste call'
+            TabOrder = 1
+            OnClick = GenCallButton1Click
+          end
+        end
+        object RefreshButton2: TBitBtn
+          Left = 14
+          Top = 10
+          Width = 75
+          Height = 25
+          Caption = 'Re&fresh'
+          TabOrder = 4
+          OnClick = RefreshButton1Click
+        end
+      end
+    end
+  end
+  object StatusBar: TStatusBar
+    Left = 0
+    Top = 292
+    Width = 412
+    Height = 19
+    Panels = <>
+    SimplePanel = True
+  end
+  object Timer1: TTimer
+    Interval = 2000
+    OnTimer = Timer1Timer
+    Left = 347
+    Top = 216
+  end
+end

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1055 - 0
Components/BMDThread/Source/BMDThreadEditors.pas


BIN
Components/BMDThread/Source/BMSpinEditPack.res


+ 42 - 0
Components/BMDThread/Source/BMThreadDsnD7.cfg

@@ -0,0 +1,42 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O-
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W+
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-N"E:\DelphiTemp"
+-LE"..\Bin"
+-LN"d:\program files\borland\delphi7\Projects\Bpl"
+-Z
+-w-SYMBOL_DEPRECATED
+-w-SYMBOL_PLATFORM
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST

+ 145 - 0
Components/BMDThread/Source/BMThreadDsnD7.dof

@@ -0,0 +1,145 @@
+[FileVersion]
+Version=7.0
+[Compiler]
+A=8
+B=0
+C=1
+D=1
+E=0
+F=0
+G=1
+H=1
+I=1
+J=0
+K=0
+L=1
+M=0
+N=1
+O=0
+P=1
+Q=0
+R=0
+S=0
+T=0
+U=0
+V=1
+W=1
+X=1
+Y=1
+Z=1
+ShowHints=1
+ShowWarnings=1
+UnitAliases=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+NamespacePrefix=
+SymbolDeprecated=0
+SymbolLibrary=1
+SymbolPlatform=0
+UnitLibrary=1
+UnitPlatform=1
+UnitDeprecated=1
+HResultCompat=1
+HidingMember=1
+HiddenVirtual=1
+Garbage=1
+BoundsError=1
+ZeroNilCompat=1
+StringConstTruncated=1
+ForLoopVarVarPar=1
+TypedConstVarPar=1
+AsgToTypedConst=1
+CaseLabelRange=1
+ForVariable=1
+ConstructingAbstract=1
+ComparisonFalse=1
+ComparisonTrue=1
+ComparingSignedUnsigned=1
+CombiningSignedUnsigned=1
+UnsupportedConstruct=1
+FileOpen=1
+FileOpenUnitSrc=1
+BadGlobalSymbol=1
+DuplicateConstructorDestructor=1
+InvalidDirective=1
+PackageNoLink=1
+PackageThreadVar=1
+ImplicitImport=1
+HPPEMITIgnored=1
+NoRetVal=1
+UseBeforeDef=1
+ForLoopVarUndef=1
+UnitNameMismatch=1
+NoCFGFileFound=1
+MessageDirective=1
+ImplicitVariants=1
+UnicodeToLocale=1
+LocaleToUnicode=1
+ImagebaseMultiple=1
+SuspiciousTypecast=1
+PrivatePropAccessor=1
+UnsafeType=0
+UnsafeCode=0
+UnsafeCast=0
+[Linker]
+MapFile=0
+OutputObjs=0
+ConsoleApp=1
+DebugInfo=0
+RemoteSymbols=0
+MinStackSize=16384
+MaxStackSize=1048576
+ImageBase=4194304
+ExeDescription=BMThread Component( Design Time Editors )
+[Directories]
+OutputDir=
+UnitOutputDir=E:\DelphiTemp
+PackageDLLOutputDir=..\Bin
+PackageDCPOutputDir=
+SearchPath=
+Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;IntrawebDB_50_70;Intraweb_50_70;Rave50CLX;Rave50VCL;dclOfficeXP;ZjGridDBA_pak;ZjGridFere_DV100D7;ZjGridFere_RV100D7
+Conditionals=
+DebugSourceDirs=
+UsePackages=0
+[Parameters]
+RunParams=
+HostApplication=
+Launcher=
+UseLauncher=0
+DebugCWD=
+[Language]
+ActiveLang=
+ProjectLang=
+RootDir=E:\Program Files\Borland\Delphi7\Bin\
+[Version Info]
+IncludeVerInfo=1
+AutoIncBuild=0
+MajorVer=1
+MinorVer=0
+Release=0
+Build=0
+Debug=0
+PreRelease=0
+Special=0
+Private=0
+DLL=0
+Locale=1033
+CodePage=1252
+[Version Info Keys]
+CompanyName=
+FileDescription=
+FileVersion=1.0.0.0
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=1.0.0.0
+Comments=
+[HistoryLists\hlUnitAliases]
+Count=1
+Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+[HistoryLists\hlUnitOutputDirectory]
+Count=1
+Item0=E:\DelphiTemp
+[HistoryLists\hlBPLOutput]
+Count=1
+Item0=E:\Components\CoolTrayIcon\Bin

+ 39 - 0
Components/BMDThread/Source/BMThreadDsnD7.dpk

@@ -0,0 +1,39 @@
+package BMThreadDsnD7;
+
+{$R *.res}
+{$ALIGN 8}
+{$ASSERTIONS ON}
+{$BOOLEVAL OFF}
+{$DEBUGINFO ON}
+{$EXTENDEDSYNTAX ON}
+{$IMPORTEDDATA ON}
+{$IOCHECKS ON}
+{$LOCALSYMBOLS ON}
+{$LONGSTRINGS ON}
+{$OPENSTRINGS ON}
+{$OPTIMIZATION OFF}
+{$OVERFLOWCHECKS OFF}
+{$RANGECHECKS OFF}
+{$REFERENCEINFO ON}
+{$SAFEDIVIDE OFF}
+{$STACKFRAMES ON}
+{$TYPEDADDRESS OFF}
+{$VARSTRINGCHECKS ON}
+{$WRITEABLECONST OFF}
+{$MINENUMSIZE 1}
+{$IMAGEBASE $400000}
+{$DESCRIPTION 'BMThread Component( Design Time Editors )'}
+{$IMPLICITBUILD OFF}
+
+requires
+  rtl,
+  vcl,
+  designide,
+  vclactnband,
+  vclx,
+  BMThreadPkgD7;
+
+contains
+  BMDThreadEditors in 'BMDThreadEditors.pas' {SynchroMethodsForm};
+
+end.

BIN
Components/BMDThread/Source/BMThreadDsnD7.res


+ 40 - 0
Components/BMDThread/Source/BMThreadPkgD7.cfg

@@ -0,0 +1,40 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J+
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-N"E:\DelphiTemp"
+-LE"..\Bin"
+-LN"d:\program files\borland\delphi7\Projects\Bpl"
+-Z
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 145 - 0
Components/BMDThread/Source/BMThreadPkgD7.dof


+ 35 - 0
Components/BMDThread/Source/BMThreadPkgD7.dpk

@@ -0,0 +1,35 @@
+package BMThreadPkgD7;
+
+{$R *.res}
+{$R 'BMDThread.dcr'}
+{$ALIGN 8}
+{$ASSERTIONS ON}
+{$BOOLEVAL OFF}
+{$DEBUGINFO ON}
+{$EXTENDEDSYNTAX ON}
+{$IMPORTEDDATA ON}
+{$IOCHECKS ON}
+{$LOCALSYMBOLS ON}
+{$LONGSTRINGS ON}
+{$OPENSTRINGS ON}
+{$OPTIMIZATION ON}
+{$OVERFLOWCHECKS OFF}
+{$RANGECHECKS OFF}
+{$REFERENCEINFO ON}
+{$SAFEDIVIDE OFF}
+{$STACKFRAMES OFF}
+{$TYPEDADDRESS OFF}
+{$VARSTRINGCHECKS ON}
+{$WRITEABLECONST ON}
+{$MINENUMSIZE 1}
+{$IMAGEBASE $400000}
+{$DESCRIPTION 'BMThread Component'}
+{$IMPLICITBUILD OFF}
+
+requires
+  vcl;
+
+contains
+  BMDThread in 'BMDThread.pas';
+
+end.

BIN
Components/BMDThread/Source/BMThreadPkgD7.res