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

[分享]基于内核对象WaitableTimer实现的Timer组件,该如何处理

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

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


Delphi(Pascal) code
unit WaitTimerU;interfaceuses  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;implementationprocedure 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.


[解决办法]
支持,支持,谢谢分享。
[解决办法]
学习学习..
[解决办法]
学习学习..
[解决办法]
来学习下了
[解决办法]
围观一下
[解决办法]
学习了
[解决办法]
学习学习
[解决办法]
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
[解决办法]
有点意思。
[解决办法]

探讨
呵呵,不能这么简单就实现吧。

[解决办法]
全 
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;

热点排行