Медленный отклик кнопки в приложении WPF

Для моего приложения WPF я разработал виртуальную клавиатуру. Он отлично работает на моей машине разработки. Однако на более медленных машинах реакция на нажатие кнопки медленная. После нажатия кнопки есть задержка перед обновлением дисплея с состоянием кнопки и событием кнопки. Что я могу сделать, чтобы убрать эту задержку? Является ли проблема проблемой отображения WPF?

Думая, что это обработчик событий, который был медленным, я попробовал несколько подходов для отправки события нажатия клавиши клавиатуры. Что бы я ни пробовал, взаимодействие все еще медленное. В настоящее время я использую:

SendInput(uint nInputs, ref INPUT pInputs, int cbSize);

Импортировано из user32.dll. Мой обработчик событий упрощен до такой степени, что он только создает параметры и вызывает вышеуказанную функцию.

Я также пытался использовать следующее, но не имел лучшей производительности:

 System.Windows.Input.Keyboard.FocusedElement.RaiseEvent(...)

Как избавиться от задержки?


person Dan Vogel    schedule 11.12.2009    source источник
comment
Что делает ваш код в обработчике событий? Можете ли вы воспроизвести проблему без обработчика, привязанного к событию щелчка?   -  person Robert Jeppesen    schedule 12.12.2009


Ответы (3)


Можете ли вы сказать, что вызывает вашу задержку?

Если в вашем событии Click есть что-то медленное, вы можете использовать отдельный Thread для выполнения кода. В новом потоке, если у вас есть код, который должен быть выполнен в потоке пользовательского интерфейса, используйте Dispatcher.BeginInvoke, чтобы поставить его в очередь для выполнения, когда у пользовательского интерфейса есть время обработки. Чтобы пользовательский интерфейс оставался отзывчивым, вам нужно держать тяжелый код вне основного (UI) потока.

Если ваша виртуальная клавиатура является локальной для определенного Window, в зависимости от сложности того, что вы делаете, вы можете использовать подход, который я использовал в прошлом, когда вы просто вручную вводите символы клавиатуры в TextBox, который имеет фокус.

Отказ от ответственности: я написал этот код более двух лет назад и в результате ненавижу его. Хотя обычно я притворяюсь, что его не существует, это может вам помочь. С тех пор я улучшил его, но сама концепция не имела проблем с производительностью на более медленных машинах. Я бы процитировал блог Джеффа Этвуда о том, что код, который вы больше всего ненавидите, является вашим собственным, но...

Редактировать. Поскольку у вас все еще есть проблемы даже с пустым Click, вы можете рассмотреть другие потенциальные задержки. Максимально ли загружен ЦП пользователя на 100% от чего-то? Либо слишком тяжелые анимации, либо другое потенциальное событие? Большинство задержек пользовательского интерфейса обычно являются результатом либо максимальной загрузки ЦП, либо события, занимающего слишком много времени в потоке пользовательского интерфейса.

Одна из возможностей заключается в том, что если ваш Window имеет AllowsTransparency="True", большая часть рабочей нагрузки, которая обычно приходится на графическую карту, теперь будет отображаться в программном обеспечении и может иметь серьезные потери производительности. Кроме того, вы можете взглянуть на этот Microsoft статью об оптимизации производительности приложений WPF с некоторыми общими советами, которые могут ускорить ваша обработка.

Я бы посоветовал всем, кто разрабатывает XAML, прочитать эту последнюю статью. Разница в производительности между такими небольшими деталями, как использование TextBlock против Label или реализация DependencyProperty против INotifyPropertyChanged, действительно может складываться, и тот факт, что они проводят бенчмаркинг для каждой из них, действительно показывает важность правильного дизайна.

person Will Eddins    schedule 11.12.2009
comment
Пожалуйста, не говорите людям использовать Dispatcher.BeginInvoke, это как DoEvents() снова и снова! - person Robert Jeppesen; 12.12.2009
comment
Да, вы правы, это в основном одно и то же, и действительно нет смысла вызывать BeginInvoke(), когда вы уже находитесь в потоке. Я отредактировал свой ответ, чтобы отразить это. Я не думаю, что это так плохо, как DoEvents(), в том, что вы не заставляете поток пользовательского интерфейса выполняться, вы только ставите в очередь больше кода для выполнения в потоке, чтобы ваши события Button могли срабатывать быстрее. Но даже напечатать это объяснение звучало плохо. - person Will Eddins; 12.12.2009
comment
даже если в обработчике событий Click ничего нет, ответ все еще медленный. - person Dan Vogel; 12.12.2009
comment
Я добавил к своему ответу еще несколько предложений. Одно только Оптимизация производительности приложения WPF было бы неплохо прочитать, просто чтобы убедиться, что вы разрабатываете свой XAML и классы таким образом, чтобы это не повлияло на производительность. - person Will Eddins; 12.12.2009

Только что наткнулся на это обсуждение. У меня есть приложение WinForms, где реакция кнопки была медленной. Это произошло после того, как я обновился до 64-разрядной версии Windows 7. Я обнаружил, что если изменить цель проекта на «x86» (вместо «Любой процессор»), медленный отклик кнопки исчезнет.

person Marc Martin    schedule 21.12.2012

Если вашему обработчику событий требуется много времени для завершения, он заблокирует пользовательский интерфейс на это время. Попробуйте этот обработчик событий:

  private void button1_Click(object sender, RoutedEventArgs e)
  {
     System.Threading.Thread.Sleep(5000);
  }

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

person Robert Jeppesen    schedule 11.12.2009
comment
Я удалил весь код из своего обработчика событий. Он будет вызван, но ничего не сделает. Реакция кнопки по-прежнему очень запаздывает. После нажатия кнопки есть хорошие 3/4 секунды, прежде чем экран обновится с кнопкой в ​​нажатом состоянии. - person Dan Vogel; 12.12.2009