- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当我使用绝对时间和 waitformultipleobjects () 时,我遇到了一个可等待计时器对象的小问题。
一旦计时器收到信号,我需要重置对象,而我能找到的唯一方法是在未来不切实际的到期时间再次使用 setwaitabletimer 。这将使计时器在操作系统唤醒计时器中毫无理由地保持事件状态。我需要保留句柄,因为在某些情况下我需要重新激活计时器,并且我使用 waitformultipleobjects 数组中的计时器对象,因此关闭 FWaitTimer 句柄并不好。
我的理解是否正确,或者有更好的方法吗?
我的完整代码如下所示,请忽略其他 waitfor 对象,它只是 FWaitTimer 对象。
unit frmMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.WinXPickers, cxGraphics, cxControls, cxLookAndFeels, cxLookAndFeelPainters, dxSkinsCore,
dxSkinTheAsphaltWorld, dxSkinsDefaultPainters, cxCalendar, Vcl.ExtCtrls, cxContainer, cxEdit, dxCore, cxDateUtils, cxDropDownEdit, cxTextEdit, cxMaskEdit,
cxSpinEdit, cxTimeEdit, Vcl.Menus, Vcl.StdCtrls, cxButtons, dateutils, syncObjs, UTimer;
const
WM_WATINGDONE = WM_USER + 100;
type
TMyWaitThread = class(TThread)
private
FWaitTimer : THandle;
FTerminateEvent : TEvent;
FPeriodicTimer : TADTimer;
FWaitTime: TDateTime;
procedure SetWaitTime(const Value: TDateTime);
property WaitTime : TDateTime read FWaitTime write SetWaitTime;
public
constructor Create; overload;
constructor Create(CreateSuspended: Boolean); overload;
destructor Destroy; override;
procedure execute; override;
procedure Terminate;
end;
TForm1 = class(TForm)
cxClock1: TcxClock;
Timer1: TTimer;
cxDateEdit1: TcxDateEdit;
btnWait: TcxButton;
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnWaitClick(Sender: TObject);
private
FMyWaitThread : TMyWaitThread;
Fwaiting: Boolean;
procedure WM_WAITINGDONE(var msg : TMessage); message WM_WATINGDONE;
procedure Setwaiting(const Value: Boolean);
{ Private declarations }
property waiting : Boolean read Fwaiting write Setwaiting;
procedure WatingDone;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnWaitClick(Sender: TObject);
var
dt : TDateTime;
begin
dt := cxDateEdit1.EditValue;
FMyWaitThread.SetWaitTime(dt);
waiting := True;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
cxClock1.Time := now;
Timer1.Enabled := True;
waiting := False;
FMyWaitThread := TMyWaitThread.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FMyWaitThread.Terminate;
FreeAndNil(FMyWaitThread);
end;
procedure TForm1.Setwaiting(const Value: Boolean);
begin
Fwaiting := Value;
case Fwaiting of
True : begin
btnWait.Enabled := False;
end;
false : begin
btnWait.Enabled := True;
cxDateEdit1.EditValue := IncMinute(Now, 1);
end;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
cxClock1.Time := now;
end;
procedure TForm1.WatingDone;
begin
waiting := False;
end;
procedure TForm1.WM_WAITINGDONE(var msg: TMessage);
begin
waiting := False;
end;
{ TMyWaitThread }
function GetGUID : string;
var
uid : TGUID;
r : Integer;
begin
Result := '';
r := CreateGuid(Uid);
if r = S_OK then
begin
Result := StringReplace(GuidToString(Uid),'{', '', [rfReplaceAll]);
Result := StringReplace(result, '}', '', [rfReplaceAll]);
end;
end;
constructor TMyWaitThread.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
FWaitTimer := CreateWaitableTimer(nil, True, PWideChar(GetGUID)); // change the 'MatrixTimer' to something unique...
FTerminateEvent := TEvent.Create;
FPeriodicTimer := TADTimer.Create;
FPeriodicTimer.Interval := 10000;
end;
destructor TMyWaitThread.Destroy;
begin
FPeriodicTimer.StopTimer;
FreeAndNil(FPeriodicTimer);
FreeAndNil(FTerminateEvent);
CloseHandle(FWaitTimer);
inherited;
end;
procedure TMyWaitThread.execute;
var
EventArr : array of THandle;
begin
SetLength(EventArr, 3);
EventArr[0] := FTerminateEvent.Handle;
EventArr[1] := FWaitTimer;
EventArr[2] := FPeriodicTimer.Handle;
while not Terminated do
begin
try
case WaitForMultipleObjects(Length(EventArr), @EventArr[0], False, INFINITE) of
WAIT_OBJECT_0 : begin // terminate
OutputDebugString('Terminating.....');
Exit;
end;
WAIT_OBJECT_0+1 : begin // wait timer
OutputDebugString('Wait timer was triggered');
WaitTime := IncMinute(now, 1);
// How do I reset the FWaitTimer - I would like to keep the FWaitTimer handle so closing it is no good.
PostMessage(Form1.Handle, WM_WATINGDONE, 0, 0);
end;
WAIT_OBJECT_0+2 : begin // periodic timer
OutputDebugString('Periodic timer was triggered');
end;
end;
except on E: Exception do
// keep any exceptions inside the loop
end;
end;
end;
procedure TMyWaitThread.SetWaitTime(const Value: TDateTime);
var
WakeUpTime: LARGE_INTEGER;
SysTime : _SystemTime;
FTime : _FileTime;
begin
FWaitTime := Value;
DateTimeToSystemTime(FWaitTime, SysTime);
SystemTimeToFileTime(SysTime, FTime);
LocalFileTimeToFileTime(FTime, FTime);
WakeUpTime.LowPart := FTime.dwLowDateTime;
WakeUpTime.HighPart := FTime.dwHighDateTime;
SetWaitableTimer(FWaitTimer, WakeUpTime.quadpart, 0, nil, nil, True);
end;
procedure TMyWaitThread.Terminate;
begin
FTerminateEvent.SetEvent;
inherited;
end;
constructor TMyWaitThread.Create;
begin
Create(False);
end;
end.
最佳答案
引自 documentation (强调我的):
The thread calls the SetWaitableTimer function to activate the timer. Note the use of the following parameters for SetWaitableTimer: Use the lpDueTime parameter to specify the time at which the timer is to be set to the signaled state. When a manual-reset timer is set to the signaled state, it remains in this state until SetWaitableTimer establishes a new due time. When a synchronization timer is set to the signaled state, it remains in this state until a thread completes a wait operation on the timer object.
所以唯一的方法是再次调用SetWaitableTimer
来重置计时器的信号状态。
有两种方法可以解决您的问题,使用当前的 hack,但在 SetWaitableTimer()
之后添加 CancelWaitableTimer()
来取消计时器(其状态将保持无信号状态)
更好的解决方案是在定时器不使用时不等待它,按照 @RbMm 建议实现:
put the FWaitTimer at the 2(last) place in array - EventArr[2] := FWaitTimer and pass 3 or 2 as first argument to WaitForMultipleObjects
关于delphi - 重置有信号的可等待计时器对象句柄,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56441290/
我设置了 Helm 柄和 Helm 柄。我有tiller-deploy。昨天,我可以定期运行了。但今天我收到此错误消息 Error: could not find a ready tiller pod
我以前已将分er安装到特定的 namespace 中。 我设置了一个环境变量来设置'tiller'命名空间-但我不记得该环境变量的名称-而且似乎无法通过网络搜索找到它。 这是什么 key ? 最佳答案
当我在 View 模型中使用如下界面时 class MainViewModel @ViewModelInject constructor( private val trafficImagesR
我正在尝试找到如何在某个 fragment 相关场景中定义 Hilt 的解决方案。我有以下设置: Activity 父 fragment 1 子 fragment 1 子 fragment 2 ...
Hilt 指出如果没有@Provides 注解就不能提供这个接口(interface): interface PlannedListRepository { fun getAllLists()
我的问题非常简单明了:两个注释/示例之间有什么区别: 例子一 @Singleton class MySingletonClass() {} @Module @InstallIn(FragmentCom
我是一名优秀的程序员,十分优秀!