首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

[分享]基于内查对象WaitableTimer实现的Timer组件

2013-01-05 
[分享]基于内核对象WaitableTimer实现的Timer组件把TTimer组件的代码抄了过来,把实现计数部分改由内核对象

[分享]基于内核对象WaitableTimer实现的Timer组件
把TTimer组件的代码抄了过来,把实现计数部分改由内核对象来实现。



unit WaitTimerU;

interface

uses
  Classes, Windows, Consts;

type
  TWaitTimer = class(TComponent)
  private
    FWaitableTimer: THandle;
    FInterval: Cardinal;
    FOnTimer: TNotifyEvent;
    FEnabled: Boolean;
    procedure UpdateTimer;
    procedure SetEnabled(Value: Boolean);
    procedure SetInterval(Value: Cardinal);
    procedure SetOnTimer(Value: TNotifyEvent);
  protected
    procedure Timer; dynamic;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Enabled: Boolean read FEnabled write SetEnabled default True;
    property Interval: Cardinal read FInterval write SetInterval default 1000;
    property OnTimer: TNotifyEvent read FOnTimer write SetOnTimer;
  end;

implementation

procedure TimerAPCProc(lpArgToCompletionRoutine: Pointer; dwTimerLowValue: DWORD;
  dwTimerHighValue: DWORD); stdcall;
begin
  TWaitTimer(lpArgToCompletionRoutine).Timer;
  SleepEx(INFINITE, True);
end;

function WaitTimerThreadFun(P: Pointer): Integer; stdcall;
var
  DueTime: Int64;
begin
  with TWaitTimer(P) do
  begin
    DueTime := -Int64(Interval)*10000;
    if SetWaitableTimer(FWaitableTimer, DueTime, Interval, @TimerAPCProc, P, False) then
    begin
      SleepEx(INFINITE, True);
    end
    else
      raise EOutOfResources.Create(SNoTimers);
  end;
  Result := 0;
end;

{ TWaitTimer }

constructor TWaitTimer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FEnabled := True;
  FInterval := 1000;
  FWaitableTimer := CreateWaitableTimer(nil, False, nil);
end;

destructor TWaitTimer.Destroy;
begin
  FEnabled := False;
  UpdateTimer;
  CloseHandle(FWaitableTimer);
  inherited;
end;

procedure TWaitTimer.SetEnabled(Value: Boolean);
begin
  if Value <> FEnabled then
  begin
    FEnabled := Value;
    UpdateTimer;
  end;
end;

procedure TWaitTimer.SetInterval(Value: Cardinal);
begin
  if Value <> FInterval then
  begin
    FInterval := Value;
    UpdateTimer;
  end;
end;

procedure TWaitTimer.SetOnTimer(Value: TNotifyEvent);
begin
  FOnTimer := Value;


  UpdateTimer;
end;

procedure TWaitTimer.Timer;
begin
  if Assigned(FOnTimer) then FOnTimer(Self);
end;

procedure TWaitTimer.UpdateTimer;
var
  ID: DWORD;
begin
  CancelWaitableTimer(FWaitableTimer);
  if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
  begin
    CreateThread(nil, 0, @WaitTimerThreadFun, Self, 0, ID);
  end;
end;

end.


[解决办法]
支持,支持,谢谢分享。
[解决办法]
学习学习..
[解决办法]
学习学习..
[解决办法]
来学习下了
[解决办法]
围观一下[分享]基于内查对象WaitableTimer实现的Timer组件
[解决办法]
学习了
[解决办法]
学习学习
[解决办法]
procedure TWaitTimer.UpdateTimer;
var
  ID: DWORD;
begin
  CancelWaitableTimer(FWaitableTimer);
  if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
  begin
    CreateThread(nil, 0, @WaitTimerThreadFun, Self, 0, ID);
  end;
end;

这段修改的时候要先判断原来的线程吧, 如果存在就关闭句柄,
另外楼主析构的时候那个线程好像也没处理。

有兴趣的可以看下
http://support.microsoft.com/kb/184796/zh-cn

[解决办法]
学习,再学习
[解决办法]
学习了。
[解决办法]
mark
[解决办法]
不错。
[解决办法]
SetWaitableTimer是个不错的函数
[解决办法]
楼主的方法非常不错
有2点小建议:
1.SetWaitableTimer配合SleepEx,同样有精确问题,无法作到<15ms的精确时间触发
  WaitForSingleObject(Ex),ZwDelayExecution,同样如此
2.TimerAPCProc的执行线程是执行SleepEx等待的线程,在这个过程中调用了触发事件OnTimer,因此如果把这个组件放到界面上,同步一下比较好.
[解决办法]
支持。
[解决办法]
厲害!
[解决办法]
这个看不太懂~
[解决办法]
呵呵。。封装这个时钟类有啥子优点哒?
[解决办法]
 CreateThread(nil, 0, @WaitTimerThreadFun, Self, 0, ID);
句柄泄露
[解决办法]
支持。。。
[解决办法]
xuexixue
[解决办法]
有点意思。
------解决方案--------------------


引用:
呵呵,不能这么简单就实现吧。



请问楼主,费这么大劲自己实现一个心跳组件,你这个能有什么特别,与delphi自带的相比有什么不同之处吗?
[解决办法]
全 
32 return ulRet 321 g_lDriverSemId[DRIVER_SEM_AD0 + ucChn] 322 close(iADhandle) 323
   ulRet = CCU_ERR 324
 INT iMiliVolt = 0;..iADhandle ..;
 .. iErrNo    = AD_READ_TRYAGAIN;     /*-11 返回值表示TRY AGAIN*/
UINT8 ucReadTime = 0;UINT32 324;CHECK
if(ucChn >= CCU_AD_CHN_NUM){50, "ADP_AD_Open chn num[%d] error", ucChn);return 167;}
if (CCU_OK != ADA_SmP(322, CCU_WAIT_FOREVER)){
/* 等待响应超时  */50, "ADP_AD_Read chn[%d] ADA_SmP timeout", ucChn);return CCU_ERR_MPI_SEM_TAKE_TIMEOUT;}
ulRet = ADP_AD_Open(ucChn, &iADhandle);if(CCU_OK != ulRet){50, "ADP_AD_Read ADP_AD_Open chn num[%d] error", ucChn);ADA_SmV(322);321;}
if(CCU_OK != ADP_AD_Config(iADhandle)){50, "ADP_AD_Read Config chn[%d] Error", ucChn);323;ADA_SmV(322);222;}
    
iErrNo = AD_READ_TRYAGAIN;
/* it is necessary to delay some time before read volt, after configuration */
/*-11 返回值表示TRY AGAIN*/
/*最多读5次*/
/*while((AD_READ_TRYAGAIN == iErrNo) && (ucReadTime < 5))*/
while((iErrNo < 0) && (ucReadTime < 5))
{ADA_Sleep(10);iErrNo = read(iADhandle, &iMiliVolt, 1);ucReadTime++;}
if(iErrNo < 0) {50, "Read ADC[%d], errno[%d]", ucChn, iErrNo);323;ADA_SmV(322);return 33;}
*piVal = iMiliVolt;/*DBG_DRVADP(LP_INFO, "Read ADC[%d]: %d", ucChn, iMiliVolt);*/323;ADA_SmV(322);221;
33   g_lDriverSemId[DRIVER_SEM_DS1820_0 + ucChn] 331  iTmp = (ucResult[0] * 10) >> 1  332
INT iTmp = 0;.. fp = ..;
UINT8 ucResult[2] = {0};// 从ds18b20读出的结果,result[0]存放低八位  CHAR acStrDir[32] = {'\0'};
if(ucChn >= CCU_DS1820_CHN_NUM){50, "DS1820 chn num cannot larger than %d", CCU_DS1820_CHN_NUM);167;}
CHECK;if (CCU_OK != ADA_SmP(331, CCU_WAIT_FOREVER))
{/* 等待响应超时  */50, "ADP_Read_DS1820 ADA_SmP timeout");return CCU_ERR_MPI_SEM_TAKE_TIMEOUT;}
43(acStrDir, sizeof(acStrDir), "/dev/ds1820-%d", ucChn);//fp = open(acStrDir, "r+"); fp = open(acStrDir, O_RDONLY);
if (fp < 0){50, "Open file[%s] fail", acStrDir);ADA_SmV(331);return 31;}
#if 0 /*启动转换*/41(ucResult, sizeof(char), 1, fp);usleep(1000);#endif
/*读取转换后的值 读2个字节*/
if(2 != read(fp, ucResult, 2)){close(fp);ADA_SmV(331);return 33;}
DBG_DRVADP(LP_INFO, "Read Temp:%d-%d", ucResult[1], ucResult[0]);
/*计算温度值*/
/*ucResult[1]为符号位  为0xff时为负 0 为正*/
if (ucResult[1] == 0xff){ucResult[0] = ~ucResult[0];ucResult[0] += 1;332;iTmp = -iTmp;}else{332;}*piVal = iTmp;
close(fp);DBG_DRVADP(LP_INFO, "Current Temperature:%d", iTmp);ADA_SmV(331);221;

热点排行