Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何停止过时的UI更新?_C#_User Interface - Fatal编程技术网

C# 如何停止过时的UI更新?

C# 如何停止过时的UI更新?,c#,user-interface,C#,User Interface,假设我有一个带有GUI的C#程序,GUI的更新/刷新/显示需要0.2秒 比方说,当它仍在计算显示过程时(在这0.2秒内),会给出一个新的更新请求,因此当前的更新请求已过时。我怎样才能让它停止做这些毫无意义的过时工作,开始为新的请求计算呢 这可能不仅仅是关于UI更新。也许,对于任何函数调用,我如何使其变成“如果发出了另一个相同的调用,则放弃当前的工作,转而使用新的数据/情况” 谢谢。您正在谈论一些相当高级的线程问题。使用内置的系统控制结构,没有办法阻止消息循环完成,就像有一种方法可以中断(优雅地)

假设我有一个带有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。