给你一个我写的单元 很好用的说
unit UntTMyTimer;
interface
uses SysUtils, Classes, windows, Contnrs;
type
TTimerMM = class;
SMyTimerDoKind = (SdkMainThread, SdkTimerThread);
TTimerItem = class
private
protected
Fkind: SMyTimerDoKind;
//名字
Fname: string;
//是否有效
FEnable: boolean;
//开始记时的时间
FStartTime: Cardinal;
//间隔的时间
FInvertTime: Cardinal;
//执行的次数 -1为永久执行
FTimerCount: Smallint;
//执行的事件
FOntimerEvent: TNotifyEvent;
//=============================
procedure SetEnable(Ivalue: boolean);
procedure SetinvertTime(Ivalue: Cardinal);
public
Parent: TTimerMM; //父组件
{执行类型 是主线程来执行 还是 定时线程自己执行}
property DoKind: SMyTimerDoKind read Fkind write Fkind;
property Enable: boolean read FEnable write SetEnable;
property InvertTime: Cardinal read FInvertTime write SetinvertTime;
property Ontimer: TNotifyEvent read FOntimerEvent write FOntimerEvent;
property Name: string read Fname;
{刷新记时}
procedure ReFresh;
{参数 间隔时间 执行事件 执行次数}
constructor Create(IInvertTime: Cardinal; IOntimerEvent: TNotifyEvent; IDoCount: Smallint = -1);
end;
TTimerMM = class(TThread)
private
Fid: Cardinal;
procedure SetCheckTime(const Value: Cardinal);
protected
FTepItem: TTimerItem;
FCheckTime: Cardinal;
FActiveList: TObjectList;
FFreeTimerList: TObjectList;
FNameList: TStringList; //名称列表
function GetDefaultName: string; //获取一个默认的名字
procedure Execute; override;
{检测事件}
procedure CheckOntimer;
{执行事件}
procedure DoOntimer;
{获取一个ID}
function GetAnId: Integer;
function GetTotCount: Cardinal;
public
{*检查的间隔时间}
property CheckTime: Cardinal read FCheckTime write SetCheckTime;
{总数}
property TotCount: Cardinal read GetTotCount;
{添加一个事件}
function AddAnOnTimer(IInvertTime: Cardinal; IOntimerEvent: TNotifyEvent;
IDoKInd: SMyTimerDoKind = SdkTimerThread; IName: string = ''; IDoCount:
Smallint = -1): TTimerItem;
function GetAnTimer(IName: string): TTimerItem;
function FreeAnTimer(IName: string): boolean;
constructor Create(CreateSuspended: Boolean = False; ICheckTimer: Cardinal = 100);
destructor Destroy; override;
end;
var
Gob_MyTimer: TTimerMM;
implementation
{ TTimerItem }
var
Gob_MyTimerItem: TTimerItem;
// Gob_MyTimer: TmyTimer;
constructor TTimerItem.Create(IInvertTime: Cardinal;
IOntimerEvent: TNotifyEvent; IDoCount: Smallint);
begin
FInvertTime := IInvertTime;
FTimerCount := IDoCount;
FOntimerEvent := IOntimerEvent;
FEnable := False;
end;
procedure TTimerItem.ReFresh;
begin
Enable := True;
end;
procedure TTimerItem.SetEnable(Ivalue: boolean);
begin
FEnable := Ivalue;
FStartTime := GetTickCount;
end;
procedure TTimerItem.SetinvertTime(Ivalue: Cardinal);
begin
Enable := False;
FInvertTime := Ivalue;
Enable := True;
end;
{ TmyTimer }
procedure TTimerMM.CheckOntimer;
var
I: Integer;
Ltep: TTimerItem;
begin
for I := FActiveList.Count - 1 downto 0 do begin // Iterate
if Terminated then
break;
try
Ltep := FActiveList.Items as TTimerItem;
if Ltep.Enable then begin
if GetTickCount >= Ltep.FStartTime + Ltep.InvertTime then begin
FTepItem := Ltep;
if FTepItem.DoKind = SdkMainThread then
Synchronize(DoOntimer)
else
DoOntimer;
if Ltep.FTimerCount <> -1 then
Dec(Ltep.FTimerCount);
Ltep.Enable := True;
if Ltep.FTimerCount = 0 then
FreeAnTimer(Ltep.Name);
end;
end;
except
end;
end; // for
end;
constructor TTimerMM.Create(CreateSuspended: Boolean = False; ICheckTimer:
Cardinal = 100);
begin
inherited Create(CreateSuspended);
FCheckTime := ICheckTimer;
FActiveList := TObjectList.Create;
FFreeTimerList := TObjectList.Create;
FNameList := TStringList.Create;
FreeOnTerminate := True;
Fid := 0;
end;
destructor TTimerMM.Destroy;
begin
try
FNameList.Free;
FFreeTimerList.Free;
FActiveList.Free;
except
end;
inherited;
end;
procedure TTimerMM.DoOntimer;
begin
FTepItem.Ontimer(FTepItem);
end;
procedure TTimerMM.Execute;
begin
while not Terminated do begin
CheckOntimer;
Sleep(FCheckTime);
end; // while
end;
function TTimerMM.FreeAnTimer(IName: string): boolean;
begin
Result := False;
Gob_MyTimerItem := GetAnTimer(IName);
if Gob_MyTimerItem <> nil then begin
Gob_MyTimerItem.Enable := False;
FFreeTimerList.Add(FActiveList.Extract(Gob_MyTimerItem));
FNameList.Delete(FNameList.IndexOf(IName));
Result := True;
end;
end;
function TTimerMM.GetAnId: Integer;
begin
Inc(Fid);
Result := Fid;
end;
function TTimerMM.GetDefaultName: string;
begin
Result := Format('%s%d', [Self.ClassName, GetAnId]);
end;
function TTimerMM.GetAnTimer(IName: string): TTimerItem;
var
Lidx: Integer;
begin
Lidx := FNameList.IndexOf(IName);
if Lidx > -1 then
Result := FNameList.Objects[Lidx] as TTimerItem
else
Result := nil;
end;
function TTimerMM.GetTotCount: Cardinal;
begin
Result := FActiveList.Count + FFreeTimerList.Count;
end;
function TTimerMM.AddAnOnTimer(IInvertTime: Cardinal; IOntimerEvent:
TNotifyEvent; IDoKInd: SMyTimerDoKind = SdkTimerThread; IName: string = '';
IDoCount: Smallint = -1): TTimerItem;
begin
if IName = '' then
IName := GetDefaultName;
if FNameList.IndexOf(IName) > -1 then
raise Exception.Create('名字重复了,创建失败');
//如果有空闲的 ITEM就拿来用
if FFreeTimerList.Count > 0 then begin
Gob_MyTimerItem := FFreeTimerList.Extract(FFreeTimerList.Items[0]) as TTimerItem;
Gob_MyTimerItem.InvertTime := IInvertTime;
Gob_MyTimerItem.Ontimer := IOntimerEvent;
Gob_MyTimerItem.FTimerCount := IDoCount;
Gob_MyTimerItem.Fname := IName;
Gob_MyTimerItem.DoKind := IDoKInd;
FActiveList.Add(Gob_MyTimerItem);
FNameList.AddObject(Gob_MyTimerItem.Name, Gob_MyTimerItem);
Gob_MyTimerItem.Enable := True;
end
else begin
Gob_MyTimerItem := TTimerItem.Create(IInvertTime, IOntimerEvent, IDoCount);
Gob_MyTimerItem.Fname := IName;
Gob_MyTimerItem.Parent := Self;
Gob_MyTimerItem.DoKind := IDoKInd;
FActiveList.Add(Gob_MyTimerItem);
FNameList.AddObject(Gob_MyTimerItem.Name, Gob_MyTimerItem);
Gob_MyTimerItem.Enable := True;
end;
Result := Gob_MyTimerItem;
end;
procedure TTimerMM.SetCheckTime(const Value: Cardinal);
begin
if Value < 10 then
raise Exception.Create('时间间隔设置过小!设置失败');
FCheckTime := Value;
end;
initialization
Gob_MyTimer := TTimerMM.Create();
finalization
try
Gob_MyTimer.Terminate;
except
end;
end.