3

何千回も呼び出される関数を一度だけ実行する方法はありますか? 並べ替えのコンテナーにアイテムを追加する機能があり、リストやその他のウィンドウ (GUI スタッフ) を更新するコードがそこにあります。したがって、100 万個のアイテムを追加する必要がある場合 (その数を知ることは不可能であり、誰でもどこからでも関数を呼び出すことができます)、GUI 更新メカニズムは何度でも呼び出されます... Appart に通知する方法はありますか?不連続からの連続関数実行(およびそれを無視)?時間間隔内でadd-item関数が最後に呼び出されたときにのみ更新メカニズムを実行する安全な方法はありますか?

ありがとうございました。

4

8 に答える 8

11

Roesone、あなたのコードは壊れています。それが間違っていることを知っているので、それはあなたがそれを書き込もうとする試みに抵抗しています。おそらく、あなたが望む振る舞いを発する汚れたハックを見つけることができるでしょう-今のところ。しかし、その解決策はハックになります。もろく、エラーが発生しやすく、保守が困難です。そして特に波及効果に対して脆弱です。この機能にリモートで触れる何かのどこかでコードに小さな変更を1つ加えるとすぐに、汚れたハックが壊れて、現在よりも悪化します。

いいえ、ここでの解決策は、機能するハックを見つけることではありません。解決策は、コードを修正することです。基本的に、これは2つの関数を作成することを意味します。1つはデータをコンテナに挿入し、もう1つはそのデータを画面に表示する完全に独立した関数です。次に、これらのメソッド専用のメカニズムを設計できます。たとえば、制限なしで挿入を許可しながら、1秒間に10回画面を更新できます。

あなた自身、あなたの同僚、そして自由な世界に恩恵を与え、あなたの壊れたコードを修正してください。

于 2010-04-01T13:45:39.467 に答える
6

static booltrueの場合、関数を終了することができます。

于 2010-04-01T13:06:50.900 に答える
2

多くのアイテムを追加したい状況で、「再描画」( GUI 更新 ) をオフにする方法があればどうでしょうか?

// add one item:
window.add_item()

// add many items:
window.set_redraw(false)
window.add_many_items()
window.set_redraw(true)

その後、add_item 関数は、GUI を更新する前にフラグをチェックするだけです。1 つの項目を追加する単純なケースは変更されません。

于 2010-04-01T13:56:00.030 に答える
1

おそらく、更新を手動でトリガーする方がよいでしょう。

于 2010-04-01T13:08:23.617 に答える
0

最良のソリューション(IMHO)は、.NETがほとんどのコントロールに使用するソリューションです。

ブール値を設定し、設定されていない場合にのみGUIを更新する、ある種の「SuspendLayout」メソッドを作成します。GUIを更新する「ResumeLayout」を追加します。

このように、クラスのユーザーが1つのアイテムのみを更新する場合、何も変更する必要はありません。何度も更新する場合、そのように言うことができ、クラスはそれについて心配する必要がありません。

これにより、必要に応じてバッチ更新を最適化することもできます。つまり、リスト内により多くのスペースを事前に割り当てることができます。追加されるアイテムの数を示すオーバーライドをSuspendLayoutに追加して(SuspendLayout(int forNumberOfItems))、正しい量のスペースでリストを初期化することもできます。

于 2010-04-01T13:44:35.397 に答える
0

GUI に使用するフレームワークによって異なります。

基本的には、次の疑似コードになります。

bool g_isValueModified = false ;
Value g_value ;

void setValue(Value value)
{
   g_value = value ;
   g_isValueModified = true ;
}

void updateValueOnGUI()
{
   if(g_isValueModified)
   {
      g_isValueModified = false ;

      // put here the code to set the value in the GUI widget
   }
}

メソッドsetValueは必要なだけ呼び出す必要がありupdateValueOnGUIますが、メソッドは、たとえば 10 ミリ秒または 100 ミリ秒ごとに 1 回呼び出す必要があります。

この非同期動作を実現するには、次のいずれかを行います。

  • 生の Win32 の場合は、Win32 タイマーを使用して WinProc を呼び出します
  • 高度な GUI フレームワークでは、タイマーを使用します
  • または、高度な GUI フレームワークでは、2 つの別個のスレッドを使用します。1 つはコード実行 (set メソッドを使用) 用、もう 1 つは GUI 実行 (更新の実行) 用で、g_value と g_isValueModified がマルチスレッド セーフな方法で書き込み/読み取りされるようにします (つまり、ロック、クリティカル セクションなど)。
于 2010-04-01T15:03:30.117 に答える
0

タイマーと Win32 API の使用に問題がない場合は、SetTimer メソッドを使用してタイマーを開始し、関数が呼び出されるたびにトリガーすることができます。SetTimer の動作は、最初の呼び出しがオフになる前に同じ TimerID で再度呼び出すと、タイマーがリセットされることです。したがって、関数が呼び出されるたびに SetTimer を呼び出すことができ、最後の呼び出しから "n" ミリ秒後にタイマーがトリガーされることが保証されます。

  UINT_PTR timerID = SetTimer(NULL, someUniqueID, 1000, yourCallback);

後で KillTimer を呼び出してクリーンアップすることを忘れないでください。

SetTimer の MSDN

于 2010-04-01T13:25:18.673 に答える
0

一定期間にわたってコンテナーへの更新を集約し、この期間の後に更新アクションを実行する必要があります (言うは易く行うは難しです)。集計するのに適切なアクションとそうでないアクションを明確にすることが重要です。

本当のポイントは、ある領域のパフォーマンスが心配な場合は、その領域に集中して取り組む必要があるということです。たとえば、UI 表示の更新頻度よりもはるかに高い頻度で UI 更新アクションを実行している場合 (または、UI 表示の更新頻度よりも高い頻度で実行している場合)。実際に必要です)、それは時間間隔での更新を集約するコードです。

また、次の更新が長期間行われない場合でも、最後の通知がタイムリーに処理されるように、データ構造を古いままにしないようにする必要があります。

于 2010-04-01T13:35:23.043 に答える