Как остановить устаревшие обновления пользовательского интерфейса? - PullRequest
1 голос
/ 12 апреля 2009

Допустим, у меня есть программа на C # с графическим интерфейсом, а обновление / обновление / отображение графического интерфейса занимает 0,2 секунды.

Скажем, пока он еще вычисляет процесс отображения (в течение этих 0,2 секунд), выдается новый запрос на обновление, поэтому текущий запрос устарел. Как я могу заставить его прекратить выполнять эту бессмысленную устаревшую работу, чтобы начать вычислять новый запрос?

Это может быть связано не только с обновлением пользовательского интерфейса. Возможно, для любого вызова функции, как я могу сделать так, чтобы он стал «Если будет выполнен другой такой же вызов, откажитесь от текущей работы и перейдите вместо новых данных / ситуации»?

Спасибо.

Ответы [ 4 ]

1 голос
/ 12 апреля 2009

Возможно, для любого вызова функции, как я могу сделать так, чтобы он стал "Если будет выполнен другой такой же вызов, откажитесь от текущей работы и перейдите вместо новых данных / ситуации"?

Зачем тебе это? Вы потеряете все доказуемость в вашем коде. Вы никогда не сможете обеспечить согласованное состояние в вашей системе. Если вы хотите смоделировать это, просто связывайтесь с ПК. Разработайте программу, которая произвольно отодвигает ПК назад к вершине любого метода, в котором он находится. Вы бы быстро увидели, что система перешла в режим разработки.

0 голосов
/ 12 апреля 2009

Я не знаю, если это соответствует тому, что вам нужно, но здесь идет. Один из способов добиться такого поведения - обратить вспять проблему и отложить фактический рендеринг.

Каждый раз, когда вы получаете запрос или изменение, включите таймер. Каждый поступающий запрос будет либо начинать, либо перезапускать время. Когда таймер действительно истекает, выполните рендеринг. Он не выполняет в точности то, что вы описываете, но на самом деле он может делать то, что вам нужно, в конце концов, то есть не выполнять рендеринг для каждого запроса, поскольку рендеринг занимает слишком много времени.

Если у вас нет непрерывных запросов, это работает довольно хорошо. Очевидно, что если вы это сделаете, вы никогда не увидите ничего ...

0 голосов
/ 12 апреля 2009

Один из возможных способов - запустить поток, который обновляет графический интерфейс, прервать его и запустить другой. Как правило, это не рекомендуемая практика из-за ужасного состояния управления потоками в 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 голосов
/ 12 апреля 2009

Вы говорите о некоторых довольно сложных проблемах с потоками. Используя встроенную структуру управления системой, невозможно предотвратить завершение цикла обработки сообщений, кроме метода прерывания (изящного) другого метода.

Теперь, если эта возможность очень важна для вас, вы МОЖЕТЕ собрать все пользовательские элементы управления, и в коде рисования вашего элемента управления вы можете проверить (в поточно-ориентированном виде, конечно) логическое значение, указывающее, следует ли продолжать рисование. .

Но если я смогу сделать удар в темноте, я догадываюсь, что вы на самом деле явно не выполняете многопоточность. Если это так, то сценарий, который вы описываете, вообще не может произойти, так как процесс обновления GUI завершится до того, как может начаться другой (а именно, этот анонимный процесс, который вы описываете, который требует другого обновления или считает текущую одну несвежую). Поскольку код в одном и том же потоке выполняется последовательно, у несвязанного куска кода действительно нет возможности вызвать обновление.

Семантика того, как и когда происходит перерисовка (например, разница между Invalidate () и Refresh (), и их соответствующее влияние на эту логику) - тема, которая, вероятно, действительно вас не интересует. Просто знай, что если ты ...

  • Занимаясь многопоточностью, вы должны реализовать свой собственный код для проверка, является ли текущий операция должна продолжаться (для Пользовательский интерфейс, это означает, что пользовательские элементы управления с это логика в логике краски)
  • Не делать многопоточность, то, что вы описать никогда не получится.

Надеюсь, это полезно!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...