Answer

专注于Mobile,WinCE
  首页  :: 新随笔  :: 联系 :: 管理
最近在WM手机上做一个水尺识别的项目,就是用手机不间断监测水库水位信息,把代码调差不多的时候,发现了一个问题,就是手机在拔掉USB线后运行程序,过一段时间手机会自动进入待机状态,导致CPU休眠,最后程序也就停止运行了.

首先看看MSDN的介绍吧:   http://msdn.microsoft.com/en-us/library/aa932196.aspx

这涉及到电源的管理方案.

刚开始我在注册表里找到

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\Timeouts

具体值如下:

从上面可以看出,在有AC电源的情况下, 60秒后会自动待机,在有电源的情况下也是60秒,这两个值都可以通过手机的电源管理上设置,也可以直接修改注册表.

我通过修改注册表的方法,把ACSuspendTimeOut 和BattSuspendTimerout值都设成零后,发现结果还是一样,程序还是会进入休眠状态。

最后通过调用下面的函数解决问题:

void KeepAlive()
{
SystemIdleTimerReset();
SHIdleTimerReset();
}

具体方法是通过一个定时器,定时的调用这个函数,就可以让程序保持非待机状态,最后完美的解决问题!

看看这两个函数在MSDN中的介绍吧:

SystemIdleTimerReset

Requirements

OS Versions: Windows CE 2.0 and later.
Header: Winuser.h.

This function resets a system timer that controls whether or not the device will automatically go into a suspended state.

void WINAPI SystemIdleTimerReset(void); 

Parameters

None.

Return Values

None.

Remarks

The default behavior is to go into a suspended state after a specified period of time expires. This time interval is specified in the registry. Calling SystemIdleTimerReset overrides the registry setting by resetting the timer.

If the Power Manager is managing timeouts, calls to SystemIdleTimerReset will still reset the GWES timeout and cause the screen saver to stop showing.

This function must be use appropriately. On battery powered devices, a program that never suspends (or sleeps) by continually calling SystemIdleTimerReset can quickly drain the batteries.

The frequency in which to call SystemIdleTimerReset in order to keep a device awake can be determined retrieving the following registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power

Requirements

OS Versions: Windows CE 2.0 and later.
Header: Winuser.h.

SHIdleTimerReset

Requirements

Smartphone: Windows Mobile 2002 and later
OS Versions: Windows CE 3.0 and later
Header: tpcshell.h
Library: aygshell.lib

This function prevents the shell from reverting to the Home screen and locking the device, when it is called periodically.

void WINAPI SHIdleTimerReset();

Parameters

None.

Return Values

None.

Remarks

To prevent the shell from reverting to the Home screen and locking the device, an application should call this function periodically. The minimum time-out that a user can specify in Settings is 10 seconds. Therefore, an application must call this function at least every 10 seconds to prevent the shell from reverting to the Home or Device lock. However, to conserve battery power, an application should call this function, on a timer, only while the user is performing operations. Otherwise, the application should allow the device to revert to Home or Device lock.

Requirements

Smartphone: Windows Mobile 2002 and later
OS Versions: Windows CE 3.0 and later
Header: tpcshell.h
Library: aygshell.lib

下面是在一个老外的网站看到的:

If you want your program to not be put to sleep while it's running, the best way is to create a KeepAlive type function that calls SystemIdleTimerReset, SHIdleTimerReset and simulates a key touch. Then you need to call it a lot, basically everywhere.

#include <windows.h> #include <commctrl.h> extern "C" { void WINAPI SHIdleTimerReset(); }; void KeepAlive() { static DWORD LastCallTime = 0;      DWORD TickCount = GetTickCount(); if ((TickCount - LastCallTime) > 1000 || TickCount < LastCallTime) // watch for wraparound { SystemIdleTimerReset(); SHIdleTimerReset();          keybd_event(VK_LBUTTON, 0, KEYEVENTF_SILENT, 0);          keybd_event(VK_LBUTTON, 0, KEYEVENTF_KEYUP | KEYEVENTF_SILENT, 0); LastCallTime = TickCount; } } 

This method only works when the user starts the application manually.

If your application is started by a notification (i.e. while the device is suspended), then you need to do more or else your application will be suspended after a very short period of time until the user powers the device out of suspended mode. To handle this you need to put the device into unattended power mode.

if(!::PowerPolicyNotify (PPN_UNATTENDEDMODE, TRUE)) { // handle error } // do long running process if(!::PowerPolicyNotify (PPN_UNATTENDEDMODE, FALSE)) { // handle error } 

During unattended mode use, you still need to call the KeepAlive a lot, you can use a separate thread that sleeps for x milliseconds and calls the keep alive funcation.

Please note that unattended mode does not bring it out of sleep mode, it puts the device in a weird half-awake state.

So if you start a unattended mode while the device in suspended mode, it will not wake up the screen or anything. All unattended mode does is stop WM from suspending your application. Also the other problem is that it does not work on all devices, some devices power management is not very good and it will suspend you anyway no matter what you do.


 转自:

http://hi.baidu.com/wangwenfang521/blog/item/a63236f3314c2cc60a46e0b5.html