トップレベルウィンドウを持つスレッドから SetSuspendState を呼び出した場合スリープ状態に入るまで時間がかかる

現象
トップレベルウィンドウを所有するスレッドから SetSuspendState を呼び出した場合、トップレベルウィンドウを所有しないスレッドから呼び出した場合よりもスリープ状態へ移行するまで時間がかかります。
原因
システムの電源状態が変わる場合、Windows は全てのトップレベルウィンドウに対して WM_POWERBROADCAST メッセージをブロードキャストして変更を通知します。WM_POWERBROADCAST メッセージは SetSuspendStateを呼び出したスレッドからではなく、システムの csrss.exe プロセスから送信されます。Windows は各トップレベルウィンドウに対してメッセージに応答する時間を最大 2 秒与えます。しかしトップレベルウィンドウを持つスレッドのメッセージポンプが停止している場合、応答を返すことができず、タイムアウトまで待機する状態が発生します。

トップレベルウィンドウを持つスレッドから SetSuspendState を呼び出した場合、SetSuspendState を呼び出したスレッドは、この処理が返るまでメッセージポンプが停止状態になるため、システムから送られてきたメッセージに応答することができません。このため、トップレベルウィンドウを持たないスレッドから SetSuspendState を呼び出した場合よりもスリープ状態へ移行する時間がかかります。
解決方法
SetSuspendState を Windows アプリケーションから呼び出す場合、トップレベルウィンドウを持たないスレッドから呼び出します。対応策の一つとして、SetSuspendState を呼び出す専用のスレッドを作成する方法があります。

詳細
可視、不可視を含む全てのトップレベルウィンドウは、ブロードキャストされたウィンドウ メッセージを受け取ります。スレッドが直接トップレベルウィンドウを作成しなくても、内部的に作成されて所有する場合があります。例えば COM オブジェクトを OleInitialize、 CoInitialize または CoInitializeEx (COINIT_SINGLETHREADED) からシングル スレッド アパートメント (STA) で作成した場合、不可視のトップレベルウィンドウが作成されます。

.NET アプリケーションから Application.SetSuspendState メソッドを呼び出す場合、トップレベルウィンドウを所有しない、そして STAThread 属性を持たないスレッドから呼び出すようにします。

また、Windowsの既存のユーザーインターフェースからの操作によるスリープ (チャーム -> 設定 -> 電源 -> スリープ)処理は、SetSuspendState の呼び出しをトップレベルウィンドウを持たないスレッドから実行しています。このため遅延は発生しません。
注意 : これは、マイクロソフトのサポート組織内で直接作成された "緊急公開" の資料です。 この資料には、確認中の問題に関する現状ベースの情報が記載されています。 情報提供のスピードを優先するため、資料には誤植が含まれる可能性があり、予告なしに随時改定される場合があります。 その他の考慮事項については、使用条件を参照してください。
プロパティ

文書番号:3007180 - 最終更新日: 09/29/2016 15:51:00 - リビジョン: 4.0

Microsoft Windows Software Development Kit for Windows Vista and .Net Framework 3.0 Runtime Componen, Windows Software Development Kit for Windows 7 and .NET Framework 4, Windows Software Development Kit for Windows 7 and Microsoft .NET Framework 3.5 Service Pack 1: Rele, Windows Software Development Kit for Windows 8, Windows Software Development Kit for Windows 8.1

  • KB3007180
フィードバック