假设我有一个带有GUI的C#程序,GUI的更新/刷新/显示需要0.2秒。
说,虽然它仍在计算显示过程(在0.2秒内),但是会给出新的更新请求,因此当前的更新请求已过时。如何让它停止做这个毫无意义的过时工作来开始为新请求计算?
它可能不仅仅是关于UI更新。也许,对于任何函数调用,我怎样才能使它成为“如果发出了同一个调用的另一个,放弃当前的工作并转而使用新的数据/情境”?
感谢。
答案 0 :(得分:1)
也许,对于任何函数调用,如何使它成为“如果发出另一个相同的调用,放弃当前的工作并转而使用新的数据/情境”?
你为什么要这样?您将失去代码中的所有可证明性。您永远无法确保系统中的一致状态。如果你想模拟它,只需弄乱PC。设计一个程序,任意将PC推回到它所在的任何方法的顶部。你很快就会看到系统的转移。
答案 1 :(得分:0)
您正在谈论一些相当高级的线程问题。使用内置的系统控制结构,除了有一种中断(优雅地)另一种方法的方法之外,没有办法阻止消息循环完成。
现在,如果此功能对您非常重要,您可以构建所有自定义控件,并且在您的控件的绘制代码中,您可以检查(当然是以线程安全的方式)一个布尔值,指示绘画是否应该继续
但是,如果我能在黑暗中进行刺杀,我会猜测你实际上并没有明确地做任何多线程。如果是这种情况,那么您描述的场景实际上不可能实际发生,因为刷新GUI的过程将在另一个可以开始之前完成(即,您正在描述的这个匿名过程要求另一次刷新或认为目前的陈旧故事)。因为同一个线程上的代码是按顺序执行的,所以实际上没有机会让不相关的代码片段导致更新。
重新绘制的方式和时间的语义(例如,Invalidate()和Refresh()之间的区别,以及它们对此逻辑的各自影响)是您可能真正感兴趣的主题。只要知道,如果你......
希望这有用!
答案 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)
如果这映射到你需要的东西,我不知道,但是这里有。 实现这种行为的一种方法是扭转问题并延迟实际渲染。
每当您收到请求或更改时,请关闭计时器。每个进入的请求都将启动或重新启动时间。 当计时器实际过去时,执行渲染。 它并没有完全按照你描述的那样做,但它实际上可能最终会做你需要的,而不是为每个请求呈现,因为渲染需要的时间太长。
如果您没有连续请求,则效果相当不错。显然,如果你这样做,你永远不会得到任何东西......