C# 如何停止过时的UI更新?
假设我有一个带有GUI的C#程序,GUI的更新/刷新/显示需要0.2秒 比方说,当它仍在计算显示过程时(在这0.2秒内),会给出一个新的更新请求,因此当前的更新请求已过时。我怎样才能让它停止做这些毫无意义的过时工作,开始为新的请求计算呢 这可能不仅仅是关于UI更新。也许,对于任何函数调用,我如何使其变成“如果发出了另一个相同的调用,则放弃当前的工作,转而使用新的数据/情况”C# 如何停止过时的UI更新?,c#,user-interface,C#,User Interface,假设我有一个带有GUI的C#程序,GUI的更新/刷新/显示需要0.2秒 比方说,当它仍在计算显示过程时(在这0.2秒内),会给出一个新的更新请求,因此当前的更新请求已过时。我怎样才能让它停止做这些毫无意义的过时工作,开始为新的请求计算呢 这可能不仅仅是关于UI更新。也许,对于任何函数调用,我如何使其变成“如果发出了另一个相同的调用,则放弃当前的工作,转而使用新的数据/情况” 谢谢。您正在谈论一些相当高级的线程问题。使用内置的系统控制结构,没有办法阻止消息循环完成,就像有一种方法可以中断(优雅地)
谢谢。您正在谈论一些相当高级的线程问题。使用内置的系统控制结构,没有办法阻止消息循环完成,就像有一种方法可以中断(优雅地)另一种方法一样 现在,如果此功能对您非常重要,您可以构建所有自定义控件,并在控件的绘制代码中检查(当然是以线程安全的方式)一个布尔值,该值指示是否应继续绘制 但是如果我可以在黑暗中尝试一下,我会猜测你实际上并没有显式地做任何多线程处理。如果是这种情况,那么您所描述的场景就永远不会真正发生,因为刷新GUI的过程将在另一个GUI开始之前完成(即,您所描述的这个匿名过程需要另一个刷新或认为当前GUI过时)。因为同一线程上的代码是按顺序执行的,所以实际上不相关的代码片段不可能导致更新 重新绘制如何以及何时发生的语义(例如,Invalidate()和Refresh()之间的区别,以及它们各自对该逻辑的影响)可能不是您真正感兴趣的主题。只要知道如果你
- 在执行多线程时,您将 必须实现自己的代码 检查当前的 操作应继续(对于 UI,这意味着具有 此逻辑在绘制逻辑中)
- 不是 做多线程,那你怎么办 描述永远不会发生
希望这是有帮助的 您正在谈论一些相当高级的线程问题。使用内置的系统控制结构,没有办法阻止消息循环完成,就像有一种方法可以中断(优雅地)另一种方法一样 现在,如果此功能对您非常重要,您可以构建所有自定义控件,并在控件的绘制代码中检查(当然是以线程安全的方式)一个布尔值,该值指示是否应继续绘制 但是如果我可以在黑暗中尝试一下,我会猜测你实际上并没有显式地做任何多线程处理。如果是这种情况,那么您所描述的场景就永远不会真正发生,因为刷新GUI的过程将在另一个GUI开始之前完成(即,您所描述的这个匿名过程需要另一个刷新或认为当前GUI过时)。因为同一线程上的代码是按顺序执行的,所以实际上不相关的代码片段不可能导致更新 重新绘制如何以及何时发生的语义(例如,Invalidate()和Refresh()之间的区别,以及它们各自对该逻辑的影响)可能不是您真正感兴趣的主题。只要知道如果你
- 在执行多线程时,您将 必须实现自己的代码 检查当前的 操作应继续(对于 UI,这意味着具有 此逻辑在绘制逻辑中)
- 不是 做多线程,那你怎么办 描述永远不会发生
希望这是有帮助的 一种可能的方法是启动一个更新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);
// ...
}
}
公共静态类控制扩展
{
公共静态TResult InvokeEx(此TControl控件,
Func Func)
其中TControl:Control
{
if(control.invokererequired)
return(TResult)control.Invoke(func,control);
其他的
返回函数(控制);
}
}
公共部分类Form1:Form
{
公共表格1()
{
初始化组件();
}
线程guiUpdateThread=null;
public void BeginLongGuiUpdate(MyState状态)
{
if(guiUpdateThread!=null&&guiUpdateThread.ThreadState!=ThreadState.Stopped)
{
guiUpdateThread.Abort();
guiUpdateThread.Join();//等待线程中止
}
guiUpdateThread=新线程(LongGuiUpdate);
guiUpdateThread.Start(状态);
}
私有void LongGuiUpdate(对象状态)
{
MyState MyState=状态为MyState;
// ...
睡眠(200);
this.InvokeEx(f=>f.Text=myState.NewTitle);
// ...
}
}
一种可能的方法是启动一个更新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);
// ...
}
}
公共静态类控制扩展
{
公共静态TResult InvokeEx(此TControl控件,
Func Func)
其中TControl:Control
{
if(control.invokererequired)
return(TResult)control.Invoke(func,control);
其他的
返回函数(控制);
}
}
公共部分类Form1:Form
{
公共表格1()
{
初始化组件();
}
线程guiUpdateThread=null;
public void BeginLongGuiUpdate(MyState状态)
{
if(guiUpdateThread!=null&&guiUpdateThread.ThreadState!=ThreadState.Stopped)
{
guiUpdateThread。