2011-12-07 13 views
5

私のアプリケーションは、特定の複雑な数学的アルゴリズムを実行するウィンドウアプリケーションです。私は長い時間前にアプリケーションを使い始めたので、そのほとんどはまだシングルスレッドです。より正確には、メインスレッドはすべての複雑な計算ロジックを実行します。計算中に、画面上にいくつかの進捗状況を表示することは重要です。あなたのアプリケーションがまだビジー状態だと思うようにWindowsを欺く方法。

ほとんどの場合、数学的アルゴリズムは数秒しかかかりませんので、ユーザーがアクションを開始すると、砂時計(またはWindows 7では実行中の円)が表示され、数秒後に結果が表示されます。

場合によっては、アルゴリズムに数分かかることがあります。この時間の間、私は砂時計を表示し、アルゴリズムがビジーである間に、私は自分のウィンドウに進行状況を示します。しかし、ユーザーがしばらくビジー状態になってからアプリケーションをクリックすると、ウィンドウが「より白く」なり(まったく透明でないプラスチックがウィンドウの上に置かれたように)、ウィンドウはもう更新されませんWindowsは「アプリケーションが応答していません」と報告します。

私はQtを使用しています。Qt関数QWidget :: repaintを使用して、アルゴリズムが使用中に再描画を強制します。再描画はしばらくの間機能しますが、上記のように、Windowsはしばらく後にこれをブロックするようです。

あなたのアプリケーションがまだビジー状態であることをウィンドウに伝え、ウィンドウが更新され続けるようにする正しい方法は何ですか?私が明示的なメッセージループを入力すると、ユーザーはアプリケーションで望ましくない他のアクションを引き起こす可能性があります。

  • PeekMessageを呼び出すだけで十分ですか?
  • GetMessageを呼び出すだけで十分ですか?
  • また、DispatchMessageを呼び出す必要がありますか?また、ユーザーが別のアクションを開始しないようにするにはどうすればいいですか(実際には、すべてのユーザー入力を防ぐ)
  • ウィンドウを更新するたびにこれらのメッセージの1つを呼び出すか、 ?、30秒?...)

計算ロジックを別のスレッドに移動することは、現在オプションではありません。

私はVisual Studio 2010をWindows 7で、Qt 4.7と組み合わせて使用​​しています。

+0

「ユーザーがアプリケーションで他の操作をトリガーする可能性があります。」そのようなコントロールを無効にします。 – ikegami

答えて

0

DisableProcessWindowGhosting関数(http://msdn.microsoft.com/en-us/library/ms648415(v=vs.85).aspx参照)は、アプリケーションが応答しない場合、「ゴーストウィンドウ」を表示してはならないことをWindowsに通知します。

私の同僚はそれでいくつかの実験を行なったし、次のように気づいた:

  • 進捗状況を示すアニメーションがうまく継続する(これは私が達成したかった実際にある)
  • ユーザーは、最小限に移動することができ、 ...マイナス面上のウィンドウ(大きな)
  • :アプリケーションが実際にハングしている場合、ユーザーはそう

それを殺すために、タスクマネージャを使用する必要があり、これは私の問題を解決します。

1

QApplication::processEvents()を随時呼び出すことができます(2〜3秒ごとなど)。これにより、再描画イベントが発生し、プログレスバーやその他の要素が更新されます。ここ

1

同様の質問や情報がたくさん:あなたはおそらく既に知っているよう I need a message pump that doesn't mess up my open window

はしかし、これは非常にハックされ、別のスレッドにコードを移動しようとする方が良いだろう。なぜこれは「オプションではないのですか?

+0

リンクをありがとう。これを独立したスレッドに移動することは現在のところ選択肢ではありません。なぜならvia経由のUIコードを呼び出す計算アルゴリズムにはまだ古いコードがたくさんあるからです(それはダイアログを表示するかもしれません:-))。興味深いもの: – Patrick

5

GUIをアプリケーションロジックから分離する必要があります。他のすべてのソリューションはハックです。計算ロジックを別のスレッドに移動することは、わずかな努力を払ってQtで簡単に達成できます。

私は、これらの時間を浪費する数学的操作をすべて実行する関数があるとします(​​と呼ぶことができます)。 1つのオプションは、低レベルのスレッド処理を使用せずに、この関数を別のスレッドで呼び出すためにQt Concurrent APIを使用することです。

QtConcurrent ::実行()関数は、別のスレッドで関数を実行します:あなたが必要なもの

QtConcurrent::run機能です。 関数の戻り値は、QFutureの APIを通じて使用できます。

QFuture<void> future = QtConcurrent::run(this, &A::execute); 

あなたが得るためにQFutrureWatcherを使用することができます。代わりに、単にあなたが次の操作を行うことができ、あなたのユーザーインターフェイスをブロックします​​を呼び出すの

Aが​​が定義されているクラスであるとします)機能が終了したときに通知されます。

+0

私はそれを見てみましょう。 – Patrick

関連する問題