はじめに
この数年で2000/XPだった環境が一気にVista/Windows7に変わり、マシン(処理)が速くなったと喜ぶ声を聴きます。しかし、処理速度が上がったにもかかわらず、今までよりも頻繁にキャプションに「(応答なし)」と表示されてしまっているのではないでしょうか。
本稿では、この「(応答なし)」がなぜ出てしまうのか、どうしたら意図しない「(応答なし)」を表示させずに済ませることができるのかを、C++とWin32の最新テクノロジを用いてチップス的に紹介したいと思います。
対象読者
- C++でWindowsアプリケーションのプログラム開発経験がある開発者
必要な環境
- Visual C++ 2010 Express Editionまたはそれ以上のエディションがインストールされた環境
なぜ「(応答なし)」が表示されるのか?
そもそもWindows OSは、何を基準としてキャプションに「(応答なし)」と表示しているのでしょうか。その答えは、Windowsが動く仕組みの根幹を支えるWindowメッセージを処理する仕組みにあります。
Windowsはメッセージが滞りなく処理されることでアプリケーションやOS全体がスムースに動作するように作られています。このメッセージ処理をスムースに行う仕組みが通称メッセージループと呼ばれる小さなループルーチンです。このループはメッセージを処理する必要のあるスレッドごとに必ず1つ以上存在し、心臓が繰り返し脈打って血液を流し続けるように一定の間隔以下でメッセージを処理するようにプログラムが設計されている必要があります。しかし、何かのメッセージを受け取ってその中で時間のかかる処理を行っていると、メッセージを処理できなくなってしまい、一定の時間が経過すると「(応答なし)」が表示されてしまうのです。
「時間のかかる処理」とは
作業を行っている間、ユーザーからの入力を実質的に受け入れることができない状況が続くことをさします。
コンピュータを使っていて、ソフトウェアの反応がないと、誰もがあれ? おかしい? と感じます。この時、おかしいと思い始めるまでの時間は多少の個人差はあるものの、おおむね0.5秒から0.7秒程度と言われています。
何か作業を行う場合、その処理に0.5秒以上かかる可能性があるかで、作業に時間がかかるかという判断を行うようにすれば(もちろん、実行対象となるマシンのスペックで最も遅いものを基準とした場合の時間です)、多くの場合ユーザーにストレスを与えることなく作業終了を待ってもらえる可能性があります。
時間のかかる処理の切り分け
時間のかかる処理といっても、呼び出したら最後終わるまで帰ってこないということは実際にはほとんどなく(0ではありません)、大抵は何らかのデータ集合(DBであったり、配列であったり)に対して連続的な操作を行った結果時間がかかる、もしくは非定型的ではあるものの多数の小さな処理を連続的に呼び出すため、結果として時間がかかるという状況ではないかと思われます。
このように一概にこうであるとはならない処理が大半ではあるものの、言葉からも分かるように1つ1つの処理は小さな(あまり時間のかからない)ものが連続して処理されることにより、結果として体感できるほどの時間がかかってしまうという特徴があります。
本稿では時間のかかる処理として、ごく単純ではあるものの、CPUパワーを全力で利用するビジーループを用意しました。これは、CPUの処理時間をタスクマネージャで目視できるようにするためにわざわざ用意したもので、内容そのものは特に意味のあるものではありません。
void BusyLoop( DWORD dwTime ) { DWORD dwStart = GetTickCount(); while( (GetTickCount()-dwStart) < dwTime ); }
「(応答なし)」を体験しよう!
まずは「(応答なし)」そのものを体験してみましょう。サンプルプログラムの体験メニューにそれぞれのOS用の体験メニューが用意されています。と言ってもごく単純に、XPなら60秒、Vistaは5秒、Windows 7は10秒という時間で、上記のBusyLoopを呼び出しているだけです。
XPの場合は、処理が始まったら、別のソフトをアクティブにして、それから戻ってくると、応答なしを見ることができます(ループ開始後10秒程度たたないと発生しません)。それ以外のOSでは、キャプションを注視していれば「(応答なし)」を見ることができます。