Что-то я не понимаю о ожидаемых таймерах. Я искал в Интернете и читал спецификации на MSDN плюс все, что мог найти в stackoverflow (например, link), но мои таймеры срабатывают почти сразу после остановки ПК.Понимание ожидаемых таймеров
Чтобы сосредоточиться на проблеме, которую я написал небольшую тестовую программу, используя xe5 (64-бит) в Windows 7 и пытались дублировать проект здесь: http://www.codeproject.com/Articles/49798/Wake-the-PC-from-standby-or-hibernation
Я думал, что проблема была, как я получить время, но Кажется, я не могу найти проблему.
Тест приложение выглядит следующим образом (очень простой):
Я объявляю тип резьбы следующим
type
TWakeupThread = class(TThread)
private
FTime: LARGE_INTEGER;
protected
procedure Execute; override;
public
constructor Create(Time: LARGE_INTEGER);
end;
...
constructor TWakeupThread.Create(Time: LARGE_INTEGER);
begin
inherited Create(False);
FreeOnTerminate:=True;
FTime:=Time;
end;
procedure TWakeupThread.Execute;
var
hTimer: THandle;
begin
// Create a waitable timer.
hTimer:=CreateWaitableTimer(nil, True, 'WakeupThread');
if (hTimer <> 0) then
begin
//CancelWaitableTimer(hTimer);
if (SetWaitableTimer(hTimer, FTime.QuadPart, 0, nil, nil, True)) then
begin
WaitForSingleObject(hTimer, INFINITE);
end;
CloseHandle(hTimer);
end;
end;
Теперь, когда нажата кнопка «Установить таймер». Я рассчитываю время файла таким образом и создаю читать.
procedure TForm1.btnSetTimerClick(Sender: TObject);
var
iUTCTime : LARGE_INTEGER;
SysTime : _SystemTime;
FTime : _FileTime;
hHandle : THandle;
dt : TDateTime;
begin
ReplaceDate(dt,uiDate.DateTime);
ReplaceTime(dt,uiTime.DateTime);
DateTimeToSystemTime(dt, SysTime);
SystemTimeToFileTime(SysTime, FTime);
LocalFileTimeToFileTime(FTime, FTime);
iUTCTime.LowPart := FTime.dwLowDateTime;
iUTCTime.HighPart := FTime.dwHighDateTime;
TWakeupThread.Create(iUTCTime);
end;
Это не работает. Кажется, что таймер срабатывает менее 2 минут после того, как система переходит в режим приостановки независимо от выбранного количества времени. Любые указания относительно того, что я делаю неправильно, будут оценены.
EDIT
Найдено этот интересный инструмент командной строки, давайте нам проверить waitable таймеры. Из команды вы можете «видеть» состояние ваших waitable таймеров, набрав:
powercfg -waketimers
я могу использовать это, чтобы подтвердить, что мои таймеры быть установлены правильно. Я также могу использовать это, чтобы подтвердить, что мои таймеры все еще работают, когда ПК преждевременно просыпается.
Используя тот же инструмент, вы можете получить список устройств, которые способны разбудить спящего режима (мыши, клавиатуры, сети в моем случае):
powercfg -devicequery wake_armed
На всех системах тестирования, команда «Powercfg - lastwake»возвращает после чего я не знаю, как расшифровать:
Wake History Count - 1
Wake History [0]
Wake Source Count - 0
Я позволил как сон и спящий режим в Windows, и оба будут просыпаться через несколько секунд. Нет активности клавиатуры и мыши, и у нас нет устройств, отправляющих запросы WOL (wake-on-lan) на эти ПК.
Мне интересно, есть ли что-то особенное, что нужно делать при вызове SetSuspendState; вот мой код:
function SetSuspendState(Hibernate, ForceCritical, DisableWakeEvent: Boolean): Boolean;
//Hibernate = False : system suspends
//Hibernate = True : system hibernates
begin
if not Assigned(_SetSuspendState) then
@_SetSuspendState := LinkAPI('POWRPROF.dll', 'SetSuspendState');
if Assigned(_SetSuspendState) then
Result := _SetSuspendState(Hibernate, ForceCritical, DisableWakeEvent)
else
Result := False;
end;
function LinkAPI(const module, functionname: string): Pointer;
var
hLib: HMODULE;
begin
hLib := GetModuleHandle(PChar(module));
if hLib =0 then
hLib := LoadLibrary(PChar(module));
if hLib <> 0 then
Result := getProcAddress(hLib, PChar(functionname))
else
Result := nil;
end;
procedure TForm1.btnSuspendClick(Sender: TObject);
begin
SetSuspendState(True, False, False);
end;
Вы уверены, что таймер пробуждает систему. Что произойдет, если вы приостановите работу системы без установки таймера. Вы также не проверяете наличие ошибок, указанных в документации. Ищите ERROR_NOT_SUPPORTED, когда SetWaitableTimer успешно завершен. –
Есть инструмент командной строки, называемый powercfg, который позволяет вам запрашивать частые таймеры и получать некоторую информацию. Из командной строки «powercfg -devicequery wake_armed» показывает, какие устройства могут разбудить ПК. У меня 5 систем; только один просыпается сам по себе (без таймера). – lowrider
@DavidHeffernan благодарит за помощь. Поэтому я вызываю GetLastError перед WaitForSingleObject и сравниваю результат с ERROR_NOT_SUPPORTED. Правильно ли это? В моих тестах GetLastError не возвращает ERROR_NOT_SUPPORTED. – lowrider