Pocket PC Power Management Series 10: A Better Way to Catch when the Device Wakes Up - Multi-Thread Code with Visual Studio 2005 Solution Download
====>SiteMap of this Blog<===
Pocket PC Power Management Series 10: A Better Way to Catch when the Device Wakes Up - Multi-Thread Code with Visual Studio 2005 Solution Download
In Pocket PC Power Management Series 4: A Better Way to Catch when the Device Wakes Up, I present a nice way to catch when the device wakes up. The sample code use CeSetUserNotificationEx to register a named event; when Windows CE OS wakes up, OS fires the event. The code has only one thread, calling MsgWaitForMultipleObjectsEx to both listen to the wakeup event, and process windows message queue. As warned at the end of that post, the single thread might be busy thus missing wakeup events.
Some readers mailed me wondering whether I can provide a fully-functional sample code with two threads such that wakeup event can be always reliably caught. A reader also left a comment asking for the two-thread code. Here I am :)
The VS2005 solution is a Zip file. Extracting it you'll get .sln, .vcproj and source code. Project settings cover Pocket PC 2003 platform and Pocket PC 5.0 platform. For PPC2003 platform, secchk.lib and ccrtrtti.lib are added.
The executable can be run on both Pocket PC 2003 device and Pocket PC 5.0 device. You can use your Pocket IE to download the executable file directly into your device, then run it there.
This is a screen cut when the program runs. All windows messages posted to the main windows (along with the timestamp) are logged to the screen. Besides, any wakeup event (along with the timestamp when the event is fired) are also logged to the screen.
Below is a quick walkthrough of the source code:
The thread that is dedicated to listening to the wakeup signal. Notice it calls WaitForMultipleObjects to actually listen to two events, the other one being the shutdown signal. This also demonstrates how to gracefully shutdown a thread without relying on a global boolean that the thread periodically polling against.
static DWORD WakeupEventListener(LPVOID lpData)
{
TCHAR szBuf[256];
PEVENTHANDLES pEventHandles = (PEVENTHANDLES)lpData;
while (TRUE) {
ResetEvent(pEventHandles->hWakeupEvent);
DWORD dwResult = WaitForMultipleObjects(2, (HANDLE*)pEventHandles, FALSE, INFINITE);
if (WAIT_OBJECT_0 == dwResult) {
_tcscpy(szBuf, TEXT("Wakeup at "));
FormatCurrentTime(szBuf+_tcslen(szBuf));
_tcscat(szBuf, TEXT("\r\n\r\n"));
OutputString(szBuf);
} else if (WAIT_OBJECT_0+1 == dwResult) {
break;
} else {
// WAIT_ABANDONED and WAIT_FAILED
// Abondoned is not possible, failed most probably means the Handle is closed
if (WAIT_FAILED == dwResult) {
// ... do something error processing
}
}
}
return S_OK;
}
Start and stop the wakeup event listener thread.
static HRESULT StartWakeupEventListener(const PEVENTHANDLES pEventHandles, HANDLE& hThread)
{
DWORD dwDummy = 0;
hThread = CreateThread(NULL, 0, WakeupEventListener, (LPVOID)pEventHandles, 0, &dwDummy);
// need to error handling if thread creation failed
return S_OK;
}
static HRESULT StopWakeupEventListener(const PEVENTHANDLES pEventHandles, HANDLE& hThread)
{
DWORD dwMilliSec = 2000;
if (hThread) {
PulseEvent(pEventHandles->hThreadStop);
DWORD dwResult = WaitForSingleObject(hThread, dwMilliSec);
if (WAIT_OBJECT_0 != dwResult) {
// error or timeout. terminate the thread anyway
TerminateThread(hThread, -1);
}
CloseHandle(hThread);
hThread = NULL;
}
return S_OK;
}
Main logic during program starts up:
- to create the wakeup event
- to create shutdown signal
- to start the wakeup event listener thread
and before the program quits:
- to stop the wakeup event listener thread,
- to destroy the wakeup event
- to destroy the shutdown signal
{
HRESULT hr = ClearWakeupNotification(g_szEventName);
hr = AddWakeupNotification(g_szEventName);
HANDLE hWakeupEvent = CreateEvent(NULL, TRUE, FALSE, g_szEventName);
HANDLE hThreadStopEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("ThreadStop"));
EVENTHANDLES eventHandles = {hWakeupEvent, hThreadStopEvent};
HANDLE hWakeupEventListenerThread = NULL;
hr = StartWakeupEventListener(&eventHandles, hWakeupEventListenerThread);
// ..........
hr = StopWakeupEventListener(&eventHandles, hWakeupEventListenerThread);
// thread handle already closed
hr = ClearWakeupNotification(g_szEventName);
CloseHandle(hWakeupEvent);
CloseHandle(hThreadStopEvent);
}
Category: [Power Management]
6 Comments:
Compiled the VS2005 solution but cannot deploy it into my PPC2003 device. Emulator is shown and gives an error related to the installation of VPC network driver. Just to let you know.
Meanwhile, DeviceWake event continues firing twice for me.
Sorry for being so fool. Did not notice about changing "target device" to PPC2003 Device.
Anyway, your example does not convince me at all.
It would be great if you can give me more specific feedback. The program works fine in both Pocket PC 2003 and Pocket PC 5.0 device. Did you download the executable to your device and run it? It logs all wakeup events in the screen so you can see the timestamp.
Ok, I meant that I needed something similar that would be tested in C#, not in C++, so that I could make it part of my PPC application in a rapid way.
If I've got time, I'll try to dive into your C++ code and translate it into C#.
Thanks anyway.
For Pocket pc, your code is working fine. But for Smart Phone it is not working. Is there any special way to findout Power notifications for smart phone specially? I am new to Smartphone programming. If I am wrong in any way please correct me.
The source code links are broken. Can you please fix them? This is exactly the type of sample code I am looking for.
Post a Comment
<< Home