如何停止过时的UI更新?

时间:2009-04-12 04:26:17

标签: c# user-interface

假设我有一个带有GUI的C#程序,GUI的更新/刷新/显示需要0.2秒。

说,虽然它仍在计算显示过程(在0.2秒内),但是会给出新的更新请求,因此当前的更新请求已过时。如何让它停止做这个毫无意义的过时工作来开始为新请求计算?

它可能不仅仅是关于UI更新。也许,对于任何函数调用,我怎样才能使它成为“如果发出了同一个调用的另一个,放弃当前的工作并转而使用新的数据/情境”?

感谢。

4 个答案:

答案 0 :(得分:1)

也许,对于任何函数调用,如何使它成为“如果发出另一个相同的调用,放弃当前的工作并转而使用新的数据/情境”?

你为什么要这样?您将失去代码中的所有可证明性。您永远无法确保系统中的一致状态。如果你想模拟它,只需弄乱PC。设计一个程序,任意将PC推回到它所在的任何方法的顶部。你很快就会看到系统的转移。

答案 1 :(得分:0)

您正在谈论一些相当高级的线程问题。使用内置的系统控制结构,除了有一种中断(优雅地)另一种方法的方法之外,没有办法阻止消息循环完成。

现在,如果此功能对您非常重要,您可以构建所有自定义控件,并且在您的控件的绘制代码中,您可以检查(当然是以线程安全的方式)一个布尔值,指示绘画是否应该继续

但是,如果我能在黑暗中进行刺杀,我会猜测你实际上并没有明确地做任何多线程。如果是这种情况,那么您描述的场景实际上不可能实际发生,因为刷新GUI的过程将在另一个可以开始之前完成(即,您正在描述的这个匿名过程要求另一次刷新或认为目前的陈旧故事)。因为同一个线程上的代码是按顺序执行的,所以实际上没有机会让不相关的代码片段导致更新。

重新绘制的方式和时间的语义(例如,Invalidate()和Refresh()之间的区别,以及它们对此逻辑的各自影响)是您可能真正感兴趣的主题。只要知道,如果你......

  • 做多线程,然后你就可以了 必须实现自己的代码 检查当前是否 操作应该继续(对于 UI,这意味着自定义控件 涂料逻辑中的这个逻辑)
  • 不 做多线程,那你是什么 描述永远不会发生。

希望这有用!

答案 2 :(得分:0)

一种可能的方法是启动一个更新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);
    // ...
  }
}

答案 3 :(得分:0)

如果这映射到你需要的东西,我不知道,但是这里有。 实现这种行为的一种方法是扭转问题并延迟实际渲染。

每当您收到请求或更改时,请关闭计时器。每个进入的请求都将启动或重新启动时间。 当计时器实际过去时,执行渲染。 它并没有完全按照你描述的那样做,但它实际上可能最终会做你需要的,而不是为每个请求呈现,因为渲染需要的时间太长。

如果您没有连续请求,则效果相当不错。显然,如果你这样做,你永远不会得到任何东西......