I’ve created a GPS program that track positions in realtime in the background for Windows mobile 6.1 in 2008-2009. It ran fine on these devices for many years. For some reason, the same code never worked perfectly on Windows Mobile 6.5.
After many hour of operations (mostly when nobody use the device), I receive a “Timeout” (code 258) from the function "WaitForMultipleObjects":
this.GPSEvent_WaitValue = WaitForMultipleObjects(2, this.GPSEvent_Handles, 0, 45000);
Again, this can work for hours and suddenly, it's just impossible to get another position without :
UPDATE:
- Restarting the device (GoogleMap confirms that there's no GPS device present!)
It has something to do with Windows Mobile going to sleep and slowing up my thread.
Here's the core code (adapted from Microsoft SDK Sample):
/// <summary>
/// When "WindowsMobile" wake up the program to check for a new position
/// </summary>
private void OnNextGPSEvent_Callback()
{
int SecondsToNextWakeUp = ETL.Mobile.Device.ScheduledCallback.MINIMUM_SECONDTONEXTWAKEUP;
switch (this.SleepingState)
{
case SleepingStateType.SleepingForNextPosition:
// Get position
this.GPSEvent_WaitValue = (WaitForEventThreadResultType)WaitForMultipleObjects(2, this.GPSEvent_Handles, 0, 45000);
switch (this.GPSEvent_WaitValue)
{
case WaitForEventThreadResultType.Event_LocationChanged:
// Got a new position
this.FireLocationChanged(this.GetCurrentPosition());
// Manage device shutdown (save battery)
if (this.PositionFrequency > MIN_SECONDS_FREQUENCY_FORDEVICE_SHUTDOWN)
{
// Close device
this.CloseDevice();
SecondsToNextWakeUp = (this.PositionFrequency - GPSDEVICE_LOAD_SECONDS_LOAD_TIME);
this.SleepingState = SleepingStateType.SleepingBeforeDeviceWakeUp;
}
else
{
// Default Wait Time
this.SleepingState = SleepingStateType.SleepingForNextPosition;
}
break;
case WaitForEventThreadResultType.Event_StateChanged:
break;
case WaitForEventThreadResultType.Timeout:
case WaitForEventThreadResultType.Failed:
case WaitForEventThreadResultType.Stop:
// >>>>>>>>>>>>>> This is where the error happens <<<<<<<<<<<<<<<<<<<<<<<<<<<
// >>>>>>>>>>>>>> This is where the error happens <<<<<<<<<<<<<<<<<<<<<<<<<<<
// >>>>>>>>>>>>>> This is where the error happens <<<<<<<<<<<<<<<<<<<<<<<<<<<
// Too many errors
this.ConsecutiveErrorReadingDevice++;
if (this.ConsecutiveErrorReadingDevice > MAX_ERRORREADINGDEVICE)
{
this.CloseDevice();
SecondsToNextWakeUp = (this.PositionFrequency - GPSDEVICE_LOAD_SECONDS_LOAD_TIME);
this.SleepingState = SleepingStateType.SleepingBeforeDeviceWakeUp;
}
else
{
// Default Wait Time
this.SleepingState = SleepingStateType.SleepingForNextPosition;
}
break;
}
#endregion
break;
case SleepingStateType.SleepingBeforeDeviceWakeUp:
this.OpenDevice();
SecondsToNextWakeUp = GPSDEVICE_LOAD_SECONDS_LOAD_TIME;
this.SleepingState = SleepingStateType.SleepingForNextPosition;
break;
}
if (this.IsListeningGPSEvent)
{
// Ajustement du prochain rappel
this.NextGPSEvent_Callback.SecondToNextWakeUp = SecondsToNextWakeUp;
this.NextGPSEvent_Callback.RequestWakeUpCallback();
}
}
/// <summary>
///Create Thread
/// </summary>
private void StartListeningThreadForGPSEvent()
{
// We only want to create the thread if we don't have one created already and we have opened the gps device
if (this._GPSEventThread == null)
{
// Create and start thread to listen for GPS events
this._GPSEventThread = new System.Threading.Thread(new System.Threading.ThreadStart(this.ListeningThreadForGPSEvent));
this._GPSEventThread.Start();
}
}
private void ListeningThreadForGPSEvent()
{
this.GPSEvent_WaitValue = WaitForEventThreadResultType.Stop;
this.IsListeningGPSEvent = true;
// Allocate handles worth of memory to pass to WaitForMultipleObjects
this.GPSEvent_Handles = Helpers.LocalAlloc(12);
Marshal.WriteInt32(this.GPSEvent_Handles, 0, this._StopHandle.ToInt32());
Marshal.WriteInt32(this.GPSEvent_Handles, 4, this._NewLocationHandle.ToInt32());
Marshal.WriteInt32(this.GPSEvent_Handles, 8, this._GPSDeviceStateChanged.ToInt32());
this.Start_NextGPSEvent_Timer(this.PositionFrequency);
this.SleepingState = SleepingStateType.SleepingBeforeDeviceWakeUp;
this.OnNextGPSEvent_Callback();
}