2009-04-12 10 views
1

私はGUIを持つC#プログラムを持っていて、GUIの更新/更新/表示に0.2秒かかるとしましょう。旧式のUIアップデートを停止するにはどうすればよいですか?

表示プロセス(この0.2秒以内)がまだ計算されているうちに、新しい更新要求が与えられているため、現在のものが古くなっています。新しい要求を計算するために、この無意味な時代遅れの作業をやめさせるにはどうすればよいですか?

UIアップデートだけではない場合もあります。多分、どのような関数呼び出しでも、同じ呼び出しの別のものが発行されると、現在の仕事を放棄し、代わりに新しいデータ/状況になるようにするにはどうすればいいでしょうか?

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

+0

どのようなUIの種類を言う必要があります。 Windowsフォーム? Webフォーム? WPF? SilverLight?また、どのバージョンの.NET? –

答えて

0

あなたはかなり高度なスレッド問題について話しています。組み込みのシステム制御構造を使用すると、メッセージループが完了するのを防ぐ方法がありません。別の方法を(優雅に)中断する方法があります。

ここで、この機能が非常に重要な場合は、すべてのカスタムコントロールを作成し、コントロールのペイントコード内で(もちろんスレッドセーフな方法で)ペイントする必要があるかどうかを示すブール値をチェックできます持続する。

しかし、私が暗闇の中で刺すことができれば、あなたは実際にマルチスレッドを明示的に行っていないと推測します。このような場合は、GUIをリフレッシュするプロセスが完了する前に、別のシナリオを開始することができるため、記述したシナリオは実際には実行できません(つまり、この匿名プロセスでは、別のリフレッシュ現在のものを古いものとみなします)。同じスレッド上のコードが順番に実行されるため、無関係なコードが更新を引き起こす機会はありません。

どのようにいつ再描画が行われるかの意味(Invalidate()とRefresh()の違い、このロジックへの影響など)は、おそらく本当に興味のないトピックです。ちょうどその時あなたは は現在 操作は、 UIのために(この手段を継続すべきか否かを確認 のために独自のコードを実装する必要があります、あなたがしている場合...

  • は、マルチスレッドを行うことを知っています ペイントロジックのこのロジックでのカスタムコントロール)
  • マルチスレッドを実行していない場合は、 は何も起こりません。

+0

コメントなしでdownvoteに感謝します。それは役に立ちます。 –

0

可能な方法の1つは、GUIを更新して中止して別のスレッドを開始するスレッドを開始することです。これはC#でのスレッド管理の恐ろしい状態のために、一般的に推奨される方法ではありませんが、心配することなくそのスレッドを回避することができます。

public static class ControlExtensions 
{ 
    public static TResult InvokeEx<TControl, TResult>(this TControl control, 
              Func<TControl, TResult> func) 
    where TControl : Control 
    { 
    if (control.InvokeRequired) 
     return (TResult)control.Invoke(func, control); 
    else 
     return func(control); 
    } 
} 

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
    InitializeComponent(); 
    } 

    Thread guiUpdateThread = null; 
    public void BeginLongGuiUpdate(MyState state) 
    { 
    if (guiUpdateThread != null && guiUpdateThread.ThreadState != ThreadState.Stopped) 
    { 
     guiUpdateThread.Abort(); 
     guiUpdateThread.Join(); // wait for thread to abort 
    } 

    guiUpdateThread = new Thread(LongGuiUpdate); 
    guiUpdateThread.Start(state); 
    } 

    private void LongGuiUpdate(object state) 
    { 
    MyState myState = state as MyState; 
    // ... 
    Thread.Sleep(200); 
    this.InvokeEx(f => f.Text = myState.NewTitle); 
    // ... 
    } 
} 
+0

これは、GUIのリフレッシュに影響しません。 Invoke(必須)の呼び出しは、メインのUIスレッドで呼び出しを実行し、完了するまでこのスレッドの実行をブロックします。待機中のスレッドを終了しても、UIスレッドに影響はありません。 –

+0

はい、中止すると、そのスレッドからの更なる更新が停止され、更新の新しいサイクルが開始されます。 – Samuel

+0

いいえ、そうではありません。そのスレッドでは更新が行われていません(そうしないと、別のスレッドからコントロールハンドルにアクセスするための例外が発生します)。更新はUIスレッドで行われており、そのスレッドは完了するまでブロックされています。ブロックされたスレッドを停止することは何もしません。 –

1

「同じコールの別が発行されている場合は、現在の仕事を放棄し、代わりに新しいデータ/状況と一緒に行き、」それはなりますので、おそらく、任意の関数呼び出しのために、どのように私はそれを作ることができますか?

なぜあなたはそれを望みますか?あなたはあなたのコードですべての証明を失うでしょう。システム内で一貫した状態を保証することはできません。あなたがそれをシミュレートしたい場合は、単にPCを台無しにする。PCを任意の方法の先頭に任意にプッシュするプログラムを設計すると、システムの移行がすぐにわかります。

0

これが必要なものにマップされていても、私は知りませんが、ここに入ります。 この種の動作を実現する1つの方法は、問題を逆転して実際のレンダリングを遅らせることです。

リクエストまたは変更が発生した場合は、いつでもタイマーを起動してください。入ってくるすべてのリクエストは、時間を開始または再開します。 タイマーが実際に経過すると、レンダリングを実行します。 これはあなたが描いたものとまったく同じではありませんが、最終的に必要なことを実際に行う可能性があります。レンダリングには時間がかかりすぎるため、それぞれの要求に対してレンダリングしません。

継続的なリクエストがない場合、これはかなりうまく動作します。明らかに、あなたがそうするなら、あなたは何も表示されません...

+0

Windowsフォームには、組み込みのメカニズムがあります。 Refresh()を呼び出すのではなく、Invalidate()を呼び出すと、メッセージループの次の反復でフォームがリフレッシュされます(コードの残りの部分は中断されません)。 –

関連する問題