如何检测 Windows Mobile 上的暂停?
我们发现 Windows Mobile 上的应用程序偶尔会丢失一些数据,并且我们怀疑当设备挂起时,某些缓冲的数据没有刷新到磁盘。 我们希望在设备即将挂起时手动将数据刷新到磁盘。 在 Windows 上,我们通过捕获 WM_POWERBROADCAST
消息来执行此操作,但此消息在 Windows Mobile 上不可用。 我在留言板上发现了一段两年前的引用 也就是说:
您需要意识到,您*不*保证您在再次醒来*之前*会收到暂停通知。 也就是说,在设备重新唤醒之前您可能不会收到通知。 一般来说,您不应该因为此限制(以及无论如何您可以对事件执行的操作的限制)而尝试对暂停做出反应。
对于所有设备来说(仍然)都是如此吗? 我们有办法做到这一点吗?
We are seeing some occasional data loss with our application on Windows Mobile, and we suspect that some buffered data is not being flushed to disk when the device is suspending. We would like to manually flush data to the disk when the device is about to suspend. On Windows, we do this by catching the WM_POWERBROADCAST
message, but this message is not available on Windows Mobile. I found a two-year-old quote on a message board that said:
You need to realize that you are *not* guaranteed that you will be notified of the suspend *before* you wake up again. That is, you might not receive the notification until after the device has been reawakened. Generally, you should not be trying to react to suspend because of this limitation (and the limitation on what you can do in response to the event, anyway).
Is this (still) true for all devices? Is there a way we can do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
据我所知,您是正确的,您无法检测设备何时进入挂起模式,只有当它使用 CeRunAppAtEvent API。
解决该问题的更好方法是尝试防止设备在代码的关键部分周围挂起。
根据应用程序的运行方式,有两种方法可以实现此目的。 如果它作为用户交互的一部分运行,您需要调用一些 API 以确保设备永远不会进入挂起模式。
您需要安排以下代码至少每 10 秒运行一次。
如果您的应用程序作为后台应用程序运行,那么您需要将代码放在无人值守的电源模式块周围,同时执行上述代码。 有关无人值守电源模式的更多详细信息,请参阅我的答案。
As far as I know you are correct that you can't detect when a device goes into suspend mode, only when it comes out using the CeRunAppAtEvent API.
A better approach to the problem is to try to prevent the device from suspending around critical parts of your code.
There are kind-of two ways to do this depending on how your application runs. If it runs as part of user interactions you need to call some API's to make sure that the device never goes into suspend mode.
You need to arrange the following code to run at least once every 10 seconds.
If you application is running as a background application then you need to put your code around a unattended power mode block while also doing the above code. See my answer for more details on unattended power mode.
这句话(听起来真的非常熟悉)仍然是正确的。 唯一保证能够在挂起之前完成其工作的组件是驱动程序,并且它们也有一系列重要的限制。
挂起背后的总体思想是对应用程序透明,而提前这样做通常不是一个好主意。
The quote (which sounds really, really familiar) is still true. The only components that are guaranteed to be able to complete their work before suspend are drivers, and they have a significant set of limitations as well.
The general idea behind a suspend is to be transparent to the application, and getting in front of that generally isn't a good idea.
您是否尝试过使用 OpenNETCF 中公开的事件? 我主要是 WinCE 爱好者,但我发现令人难以置信的是,任何人都会发布一个无法可靠地通知您电源状态更改的平台,因为这是桌面设备和移动设备之间最重要的区别之一。
Have you tried using the events that are exposed in OpenNETCF? I'm mainly a WinCE bod but I find it incredible that anyone would a release a platform that didn't reliably inform you of changes to power state as this is one of the most important differences between Desktop and Mobile device.
根据 http:// /social.msdn.microsoft.com/Forums/en-US/windowsmobiledev/thread/229dd6a2-f231-4aeb-ad90-c6995ba155cf/ 除了 Windows Mobile 上的 POWER_STATE_SUSPEND 之外,还有另一种电源状态 POWER_STATE_UNATTENDED。
如果 WM 设备被挂起,您首先会收到 POWER_STATE_UNATTENDED,然后收到 POWER_STATE_SUSPEND。
使用 ::RequestPowerNotifications() API 并过滤 PBT_TRANSITION 可以处理到 POWER_STATE_SUSPEND 和 POWER_STATE_UNATTENDED 的转换。
处理 POWER_STATE_SUSPEND 的问题在于,它通常是在设备恢复后由代码处理的。 我在网上发现了一个建议,即对调用 ::ReadMsgQueue(..., INFINITE,...) 并执行处理的线程使用实时优先级。
为此,我们需要使用特定于 CE 的 ::CeSetThreadPriority(),因为它允许设置实时优先级。 我厚颜无耻地用0优先级。
一般来说,通过这种方式,我能够可靠地处理 POWER_STATE_UNATTENDED 而不是那么可靠地处理 POWER_STATE_SUSPEND,因为我的操作相当耗时(约 2 秒)。
对于我的任务处理 POWER_STATE_UNATTENDED 是我真正需要处理的。
According to http://social.msdn.microsoft.com/Forums/en-US/windowsmobiledev/thread/229dd6a2-f231-4aeb-ad90-c6995ba155cf/ besides POWER_STATE_SUSPEND on Windows Mobile there is also another power state POWER_STATE_UNATTENDED.
If WM device is being suspended you first get POWER_STATE_UNATTENDED and then POWER_STATE_SUSPEND.
Using ::RequestPowerNotifications() API and filtering for PBT_TRANSITION it is possible to handle transitions to both POWER_STATE_SUSPEND and POWER_STATE_UNATTENDED.
The problem with handling POWER_STATE_SUSPEND is that it is typically handled by your code after device has been resumed. I found on the Web a suggestion to use real-time priority for the thread that calls ::ReadMsgQueue(..., INFINITE,...) and does the handling.
For that we need to use CE-specific ::CeSetThreadPriority() because it allows for setting real-time priorities. I shamelessly use 0 priority.
Generally, this way I was able to reliably handle POWER_STATE_UNATTENDED and not so reliably POWER_STATE_SUSPEND because I had rather time consuming operation (~2 seconds).
For my task handling POWER_STATE_UNATTENDED is what I really need to handle.
也许这个问题的答案是有帮助的: 如何在 Windows Mobile 暂停时运行代码?
Maybe the answer to this SO question is of help: How can I run code on Windows Mobile while being suspended?