1、怎么把TWaitableTimer的Self传给TimerAPCProc?这种做法对吗:
SetWaitableTimer(FHandle, DueTime, 1000, @TimerAPCProc,Pointer(self), False)procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWORD;
dwTimerHighValue: DWORD); stdcall;
var
WT :TWaitableTimer;
begin
WT := TWaitableTimer(lpArgToCompletionRoutine^);
……红色的部分传递Self。2、程序运行到下述红色语句时出错:Project Projcet1.exe raised exception
class EAccessViolation with message 'Access violation at address 004A6E40 in
module 'Project1.exe', Write of address 004A68CC'.procedure TWaitableTimer.SetElapsedTime(const Value: TDateTime);
begin
gLock.Enter;
try
FElapsedTime := Value;
finally
gLock.Leave;
end;
end;3、当剩余时间为0时,如何终止定时器?这样处理行吗?
procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer;
dwTimerLowValue: DWORD; dwTimerHighValue: DWORD); stdcall;
var
WT :TWaitableTimer;
begin
WT := TWaitableTimer(lpArgToCompletionRoutine^);
with WT do
begin
if FRemainingTime>0 then
……
else
CancelTimer;
end;
SleepEx(INFINITE, True);
end;
源程序如下:unit WaitTimer;interfaceuses
SysUtils, Classes, Windows, SyncObjs, StdCtrls;type
TWaitableTimer = class(TThread)
private
FHandle: THandle;
FStartTime: TDateTime;
FShowRT: Boolean;
FETParent: TStaticText;
FTotalTimes: TDateTime;
FElapsedTime: TDateTime;
FRemainingTime: TDateTime;
FRTParent: TStaticText; procedure SetHandle;
procedure SetShowRT(const Value: Boolean);
procedure SetStartTime;
procedure SetETParent(const Value: TStaticText);
function GetShowRT: Boolean;
procedure SetTimer(const ETSender,RTSender: TObject);
procedure SetRTParent(const Value: TStaticText);
procedure SetRTCaption(const Value: string);
public
constructor Create(const ETSender,RTSender: TObject;
const AName: String = '');
destructor Destroy(); override;
procedure Execute; override;
function CancelTimer: Boolean;
function Time2String(aTime: TDateTime): string;
procedure SetTotalTimes(const Value: TDateTime);
procedure SetElapsedTime(const Value: TDateTime);
procedure SetRemainingTime(const Value: TDateTime);
function GetTotalTimes: TDateTime;
Protected
property Handle: THandle read FHandle;
property StartTime: TDateTime read FStartTime;
property TotalTimes: TDateTime read GetTotalTimes write SetTotalTimes;
property ElapsedTime: TDateTime read FElapsedTime write SetElapsedTime;
property RemainingTime: TDateTime read FRemainingTime
write SetRemainingTime;
property ETParent: TStaticText read FETParent write SetETParent;
property RTParent: TStaticText read FRTParent write SetRTParent;
property ShowRT: Boolean read GetShowRT write SetShowRT;
end;implementation{ TWaitableTimer }
var
gLock: TCriticalSection;procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer;
dwTimerLowValue: DWORD;dwTimerHighValue: DWORD); stdcall;
var
WT :TWaitableTimer;
begin
WT := TWaitableTimer(lpArgToCompletionRoutine^);
with WT do
begin
if FRemainingTime>0 then
begin
SetElapsedTime(Now - StartTime);
FETParent.Caption := Time2String(FElapsedTime); if GetShowRT then
begin
SetRemainingTime(GetTotalTimes - FElapsedTime);
SetRTCaption(Time2String(FRemainingTime));
end;
end
else
CancelTimer;
end; SleepEx(INFINITE, True);
end;function TWaitableTimer.CancelTimer: Boolean;
begin
Result := CancelWaitableTimer(FHandle);
end;constructor TWaitableTimer.Create(const ETSender, RTSender: TObject;
const AName: String);
begin
gLock := TCriticalSection.Create; SetTimer(ETSender,RTSender); inherited Create(False);
end;destructor TWaitableTimer.Destroy;
begin
CloseHandle(FHandle);
gLock.Destroy; inherited;
end;procedure TWaitableTimer.Execute;
var
DueTime: int64;
begin
inherited; DueTime := 0; if SetWaitableTimer(
FHandle, DueTime, 1000, @TimerAPCProc, Pointer(self),False
) then
begin
SleepEx(INFINITE, True);
end;
end;function TWaitableTimer.GetShowRT: Boolean;
begin
result := False; gLock.Enter;
try
result := FShowRT;
finally
gLock.Leave;
end;
end;function TWaitableTimer.GetTotalTimes: TDateTime;
begin
result := 0; gLock.Enter;
try
result := FTotalTimes;
finally
gLock.Leave;
end;
end;procedure TWaitableTimer.SetElapsedTime(const Value: TDateTime);
begin
gLock.Enter;
try
FElapsedTime := Value;
finally
gLock.Leave;
end;
end;procedure TWaitableTimer.SetHandle;
begin
if FHandle = 0 then
FHandle := CreateWaitableTimer(nil, True, nil);
end;procedure TWaitableTimer.SetRemainingTime(const Value: TDateTime);
begin
gLock.Enter;
try
FRemainingTime := Value;
finally
gLock.Leave;
end;
end;procedure TWaitableTimer.SetRTCaption(const Value: string);
begin
if ShowRT then
RTParent.Caption := Value
else
RTParent.Caption := '计算中……';
end;procedure TWaitableTimer.SetRTParent(const Value: TStaticText);
begin
FRTParent := Value;
end;procedure TWaitableTimer.SetShowRT(const Value: Boolean);
begin
gLock.Enter;
try
FShowRT := Value;
finally
gLock.Leave;
end;
end;procedure TWaitableTimer.SetStartTime;
begin
FStartTime := Now;
end;procedure TWaitableTimer.SetTimer(const ETSender, RTSender: TObject);
begin
SetHandle;
SetStartTime;
SetTotalTimes(0);
SetElapsedTime(0);
SetRemainingTime(0);
if ETSender is TStaticText then
SetETParent(TStaticText(ETSender));
if RTSender is TStaticText then
SetRTParent(TStaticText(RTSender));
SetRTCaption('');
SetShowRT(False);
end;procedure TWaitableTimer.SetETParent(const Value: TStaticText);
begin
FETParent := Value;
end;procedure TWaitableTimer.SetTotalTimes(const Value: TDateTime);
begin
gLock.Enter;
try
FTotalTimes := Value;
if FTotalTimes<>0 then
SetShowRT(True);
finally
gLock.Leave;
end;
end;function TWaitableTimer.Time2String(aTime: TDateTime): string;
begin
DateTimeToString(result,'hh:nn:ss',aTime);
end;
end.调用如下:
unit Unit3;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WaitTimer;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
StaticText1: TStaticText;
StaticText2: TStaticText;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation
{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
var
WT: TWaitableTimer;
i: integer;
t1,t2: Int64;
begin
randomize;
WT := TWaitableTimer.Create(StaticText1,StaticText2);
t1 := GetTickCount;
for I := 0 to 1000 do
begin
Label1.Caption := inttostr(i);
Application.ProcessMessages;
Sleep(random(10));
t2 := (GetTickCount - t1) * (1000 - i);
WT.SetTotalTimes(t2);
end;
WT.Free;
end;end.
SetWaitableTimer(FHandle, DueTime, 1000, @TimerAPCProc,Pointer(self), False)procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWORD;
dwTimerHighValue: DWORD); stdcall;
var
WT :TWaitableTimer;
begin
WT := TWaitableTimer(lpArgToCompletionRoutine^);
……红色的部分传递Self。2、程序运行到下述红色语句时出错:Project Projcet1.exe raised exception
class EAccessViolation with message 'Access violation at address 004A6E40 in
module 'Project1.exe', Write of address 004A68CC'.procedure TWaitableTimer.SetElapsedTime(const Value: TDateTime);
begin
gLock.Enter;
try
FElapsedTime := Value;
finally
gLock.Leave;
end;
end;3、当剩余时间为0时,如何终止定时器?这样处理行吗?
procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer;
dwTimerLowValue: DWORD; dwTimerHighValue: DWORD); stdcall;
var
WT :TWaitableTimer;
begin
WT := TWaitableTimer(lpArgToCompletionRoutine^);
with WT do
begin
if FRemainingTime>0 then
……
else
CancelTimer;
end;
SleepEx(INFINITE, True);
end;
源程序如下:unit WaitTimer;interfaceuses
SysUtils, Classes, Windows, SyncObjs, StdCtrls;type
TWaitableTimer = class(TThread)
private
FHandle: THandle;
FStartTime: TDateTime;
FShowRT: Boolean;
FETParent: TStaticText;
FTotalTimes: TDateTime;
FElapsedTime: TDateTime;
FRemainingTime: TDateTime;
FRTParent: TStaticText; procedure SetHandle;
procedure SetShowRT(const Value: Boolean);
procedure SetStartTime;
procedure SetETParent(const Value: TStaticText);
function GetShowRT: Boolean;
procedure SetTimer(const ETSender,RTSender: TObject);
procedure SetRTParent(const Value: TStaticText);
procedure SetRTCaption(const Value: string);
public
constructor Create(const ETSender,RTSender: TObject;
const AName: String = '');
destructor Destroy(); override;
procedure Execute; override;
function CancelTimer: Boolean;
function Time2String(aTime: TDateTime): string;
procedure SetTotalTimes(const Value: TDateTime);
procedure SetElapsedTime(const Value: TDateTime);
procedure SetRemainingTime(const Value: TDateTime);
function GetTotalTimes: TDateTime;
Protected
property Handle: THandle read FHandle;
property StartTime: TDateTime read FStartTime;
property TotalTimes: TDateTime read GetTotalTimes write SetTotalTimes;
property ElapsedTime: TDateTime read FElapsedTime write SetElapsedTime;
property RemainingTime: TDateTime read FRemainingTime
write SetRemainingTime;
property ETParent: TStaticText read FETParent write SetETParent;
property RTParent: TStaticText read FRTParent write SetRTParent;
property ShowRT: Boolean read GetShowRT write SetShowRT;
end;implementation{ TWaitableTimer }
var
gLock: TCriticalSection;procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer;
dwTimerLowValue: DWORD;dwTimerHighValue: DWORD); stdcall;
var
WT :TWaitableTimer;
begin
WT := TWaitableTimer(lpArgToCompletionRoutine^);
with WT do
begin
if FRemainingTime>0 then
begin
SetElapsedTime(Now - StartTime);
FETParent.Caption := Time2String(FElapsedTime); if GetShowRT then
begin
SetRemainingTime(GetTotalTimes - FElapsedTime);
SetRTCaption(Time2String(FRemainingTime));
end;
end
else
CancelTimer;
end; SleepEx(INFINITE, True);
end;function TWaitableTimer.CancelTimer: Boolean;
begin
Result := CancelWaitableTimer(FHandle);
end;constructor TWaitableTimer.Create(const ETSender, RTSender: TObject;
const AName: String);
begin
gLock := TCriticalSection.Create; SetTimer(ETSender,RTSender); inherited Create(False);
end;destructor TWaitableTimer.Destroy;
begin
CloseHandle(FHandle);
gLock.Destroy; inherited;
end;procedure TWaitableTimer.Execute;
var
DueTime: int64;
begin
inherited; DueTime := 0; if SetWaitableTimer(
FHandle, DueTime, 1000, @TimerAPCProc, Pointer(self),False
) then
begin
SleepEx(INFINITE, True);
end;
end;function TWaitableTimer.GetShowRT: Boolean;
begin
result := False; gLock.Enter;
try
result := FShowRT;
finally
gLock.Leave;
end;
end;function TWaitableTimer.GetTotalTimes: TDateTime;
begin
result := 0; gLock.Enter;
try
result := FTotalTimes;
finally
gLock.Leave;
end;
end;procedure TWaitableTimer.SetElapsedTime(const Value: TDateTime);
begin
gLock.Enter;
try
FElapsedTime := Value;
finally
gLock.Leave;
end;
end;procedure TWaitableTimer.SetHandle;
begin
if FHandle = 0 then
FHandle := CreateWaitableTimer(nil, True, nil);
end;procedure TWaitableTimer.SetRemainingTime(const Value: TDateTime);
begin
gLock.Enter;
try
FRemainingTime := Value;
finally
gLock.Leave;
end;
end;procedure TWaitableTimer.SetRTCaption(const Value: string);
begin
if ShowRT then
RTParent.Caption := Value
else
RTParent.Caption := '计算中……';
end;procedure TWaitableTimer.SetRTParent(const Value: TStaticText);
begin
FRTParent := Value;
end;procedure TWaitableTimer.SetShowRT(const Value: Boolean);
begin
gLock.Enter;
try
FShowRT := Value;
finally
gLock.Leave;
end;
end;procedure TWaitableTimer.SetStartTime;
begin
FStartTime := Now;
end;procedure TWaitableTimer.SetTimer(const ETSender, RTSender: TObject);
begin
SetHandle;
SetStartTime;
SetTotalTimes(0);
SetElapsedTime(0);
SetRemainingTime(0);
if ETSender is TStaticText then
SetETParent(TStaticText(ETSender));
if RTSender is TStaticText then
SetRTParent(TStaticText(RTSender));
SetRTCaption('');
SetShowRT(False);
end;procedure TWaitableTimer.SetETParent(const Value: TStaticText);
begin
FETParent := Value;
end;procedure TWaitableTimer.SetTotalTimes(const Value: TDateTime);
begin
gLock.Enter;
try
FTotalTimes := Value;
if FTotalTimes<>0 then
SetShowRT(True);
finally
gLock.Leave;
end;
end;function TWaitableTimer.Time2String(aTime: TDateTime): string;
begin
DateTimeToString(result,'hh:nn:ss',aTime);
end;
end.调用如下:
unit Unit3;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, WaitTimer;type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
StaticText1: TStaticText;
StaticText2: TStaticText;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation
{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
var
WT: TWaitableTimer;
i: integer;
t1,t2: Int64;
begin
randomize;
WT := TWaitableTimer.Create(StaticText1,StaticText2);
t1 := GetTickCount;
for I := 0 to 1000 do
begin
Label1.Caption := inttostr(i);
Application.ProcessMessages;
Sleep(random(10));
t2 := (GetTickCount - t1) * (1000 - i);
WT.SetTotalTimes(t2);
end;
WT.Free;
end;end.
解决方案 »
免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货