0

これはすべて、Visual Studio 2008 の C# で行っています。

ユーザーがアルゴリズムの動作を監視できるように、アルゴリズムの動作を遅くしたいと考えています。GUI に表示される定期的な変更があるためThread.Sleep、すべてのインスタンスの後に追加しました。

問題は、Thread.Sleep少なくとも 1 秒に設定すると、Thread.Sleep(数回のループの後) のいくつかのインスタンスの後、単に GUI 全体をフリーズさせ、プログラムが完了するまでそのままにしておくことです。すぐにではありませんが、常に発生します。どのくらい早く睡眠の長さに依存します。

プログラム全体がフリーズしないという証拠があります。それは機能しており、スリープでも正しい長さの一時停止が行われています。しかし、アルゴリズムが終了するまで、特定の時点で GUI がフリーズし、その時点で正しい最終状態が表示されます。

この問題を解決するには?特定の時点でアルゴリズムを一時停止する代わりに?

4

4 に答える 4

7

まず第一に、いつ完了するかを考える前に、完了した作業をユーザーに待たせてはなりません。無意味です。ノーと言ってください。

次に、UI スレッドを「スリープ」させています。これが、UI スレッドが「ロックアップ」している理由です。UI スレッドはブロックできません。そうである場合、UI スレッドはフォーム上のコントロールを更新できず、システム メッセージに応答できません。システム メッセージへの応答は、UI スレッドの重要なタスクです。そうしないと、アプリケーションがシステムにロックされているように見えます。良いことではありません。

これを達成したい場合 (しないでください) 、作業を開始するときにTimerを作成するだけで、それがTicksになったときに、作業を行うふりをやめる時間を示します。

繰り返しますが、これを行わないでください。

于 2011-03-27T16:07:50.650 に答える
4

すべてが単一のスレッドで不足していると思います。ユーザーはおそらく、ボタンをクリックするなどしてこのアルゴリズムを呼び出します。これは、メイン スレッドのメッセージ キューによって処理されます。このイベント ハンドラーが戻るまで、アプリの GUI は更新できません。応答性を維持するには、メッセージ キューを定期的にポンプする必要があります。

スリープはほとんど良い考えではなく、GUI スレッドでは間違いなく良い考えではありません。引き続きスリープを使用し、Application.DoEvents を呼び出して GUI をレスポンシブにすることはお勧めしません。

代わりに、このアルゴリズムをバックグラウンド スレッドで実行し、完了時にメイン スレッドにその旨を通知する必要があります。

于 2011-03-27T16:06:37.297 に答える
3

あなたはいくつかのかなり一般的なユーザー インターフェイスの失敗をコミットしようとしています。

  • ユーザーに細かい点でスパムを送信しないでください。ユーザーは結果のみに関心があります。
  • 要求どおりに速く作業することをユーザーに強制しないでください
  • 忙しいときにユーザーがプログラムを操作することを禁止しないでください。

その代わり:

  • ListBox のようなガジェットに結果を表示して、ユーザーが自分のペースで結果を確認できるようにする
  • スレッドを使用してユーザー インターフェイスをインタラクティブに保つ
  • デバッガーを使用して自分の利益のために時間を遅くする
于 2011-03-27T16:19:47.583 に答える
0

これは多くのことに依存するため、あなたが言ったことから具体的な答えを出すのは難しい. それでも、関連する可能性のあるいくつかの事項を以下に示します。

これを UI スレッドで実行していますか (たとえば、作業を開始したフォーム ボタンまたは UI イベントのスレッド)? その場合は、新しいスレッドを作成して作業を実行する方がよい場合があります。

なぜあなたはまったく眠るのですか?進行中の作業に関連する状態が関連するすべてのスレッドで利用できる場合、オブザーバーは作業スレッドがスリープ状態にならずにこれを観察できないでしょうか? おそらく、作業スレッドは、現在の進行状況のインジケーターを揮発性変数またはロックされた変数に書き込むことができます (int やオブジェクトなどのポインター サイズより大きい場合はロックする必要がありますが、それ以外の場合はそうではありません。ロックされていない場合、揮発性であるとキャッシュが妨げられます。大した問題ではないかもしれませんが)。この場合、フォーム タイマー (.Net にはさまざまな目的のさまざまなタイマーがあります) を使用して、その変数のステータスを確認し、実行中の作業を反映するように UI を更新できます。作業スレッドは何もする必要はありません。せいぜい有益かもしれないYield()ときどき作業スレッドで使用されますが、これでさえ必要になる可能性は低いです。

于 2011-03-27T16:11:11.623 に答える