为什么传递SPIF_SENDCHANGE标志SystemParametersInfo会挂起?

为什么传递SPIF_SENDCHANGE标志SystemParametersInfo会挂起?

作者:BlogUpdater |  时间:2022-06-26 |  浏览:82 |  评论已关闭 条评论

如果你传递SPIF_SENDCHANGE标志给SystemParametersInfo函数,则它会向系统以广播的形式发送WM_SETTINGCHANGE消息,并将消息的wParam参数设置为你传递给函数的标志。例如,如果你调用:
SystemParametersInfo(SPI_SETDOUBLECLICKTIME,500, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);

则系统会广播下列消息:
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETDOUBLECLICKTIME, 0);

如果系统里有一个窗口没有响应这个夏熊,则广播会被挂起直到此窗口响应此消息或者此窗口被销毁。

如果你希望避免其他窗口的不响应行为,确实有一些方法,但是这也会对你的程序产生非预期的影响。

你可以通过在一个后台线程中执行SystemParametersInfo调用,那么就算被挂起,也只是这个后台线程被挂起,主界面依然正常运行。

有了这个消息,后台线程可以在广播最终完成时通知主线程,此时你的程序现在知道所有窗口都已收到它们的通知并使用新设置。

你还可以在没有 SPIF_SENDCHANGE 标志的情况下发出 SystemParametersInfo 调用,然后通过手动广播更改,如下:
DWORD dwResult;
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE,SPI_SETDOUBLECLICKTIME, 0,SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 5000, &dwResult);

这确实意味着无响应的窗口将不会收到系统参数已更改的通知。 如果你认为你的设置更改很小,以至于缺少通知的程序没什么大不了,这是可以接受的。 换句话说,当无响应的程序最终唤醒时,它不会知道设置已更改,因为它错过了通知。

你可以结合以上两种方法:使用后台线程并发送超时消息。

也许最好的技术是使用 SendNotifyMessage 函数。 如前所述,SendNotifyMessage 函数与 SendMessage 类似,只是它不等待响应。 这可以让你的程序恢复工作,而不会弄乱在你决定广播通知时暂时无响应的程序。

SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETDOUBLECLICKTIME, 0);

缺点是,你不知道所有窗口何时最终收到并处理了通知。 你所知道的是,总有一天,他们最终会发现。 通常你不关心广播的这个方面,所以这种信息的缺乏并不是一个障碍。

总结
独立,独立,独立。
在可能的情况下,尽量使你的程序和其他组件减少依赖:不调用它们的函数,不导入它们的库,不引用它们的头文件。这样,在程序的世界,你才是自由的。
注意,以上做法的前提是:在可能的情况下。

最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Why does SystemParametersInfo hang when I pass the SPIF_SENDCHANGE flag?》

最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

评论已关闭。