Почему добавление SuspendLayout и ResumeLayout снижает производительность?

Мне нужно добавить много элементов управления в родительский элемент управления.

Но я обнаружил, что если я добавляю ParentControl.SuspendLayout и ParentControl.ResumeLayout до и после добавления этих элементов управления к родителю, я использую секундомер для измерения тактов: если я удалю код ParentControl.SuspendLayout и ParentControl.ResumeLayout, это будет быстрее. Почему это происходит?

Таким образом, SuspendLayout и ResumeLayout не должны сокращать время добавления дополнительных элементов управления, верно? Итак, какая польза от использования SuspendLayout и ResumeLayout или, другими словами, если я не использую SuspendLayout и ResumeLayout, а добавляю подчиненные элементы управления непосредственно к родителям, что плохого?


person spspli    schedule 29.10.2012    source источник
comment
Сколько элементов управления вы добавляете? Если их всего несколько, то в этом нет необходимости, но если вы добавляете сотни/тысячи, вы, скорее всего, увидите разницу. Кроме того, если вы рассчитали время, какая разница между двумя временами; было ли это всего лишь какое-то небольшое количество (достаточное, чтобы быть просто случайным отклонением во времени выполнения) или оно было действительно значительным?   -  person Servy    schedule 29.10.2012
comment
Какие типы контроля вы используете? Подобная проблема описана здесь.   -  person Neolisk    schedule 29.10.2012
comment
да, я добавляю сотни элементов управления.   -  person spspli    schedule 30.10.2012
comment
Я думаю, вам нужно показать обе версии кода для любой попытки реального ответа.   -  person Alan    schedule 30.10.2012
comment
трудно определить без кода. Я использую тот же метод, очень быстро добавляя сотни динамических элементов управления без проблем, в то время как SuspendLayout   -  person Rached N.    schedule 20.11.2012
comment
Мы вызываем команду приостановки и возобновления макета, чтобы избежать запуска событий при добавлении любых элементов управления. Более того, иногда они могут вызвать мерцание при добавлении элементов управления, если вы не приостановите управление.   -  person Sandy    schedule 26.11.2012


Ответы (2)


Это происходит по обычной причине: удаление кода обычно ускоряет работу вашей программы.

Suspend/ResumeLayout() довольно часто неправильно понимают. Это будет иметь значение только в том случае, если у вас есть элементы управления, которые имеют свойство AutoSize, Dock или Anchor, отличное от значения по умолчанию. Это предотвращает аварии макета, когда элементы управления имеют свойства макета, которые влияют друг на друга.

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

person Hans Passant    schedule 07.12.2012

Вместо этого вы, вероятно, захотите использовать .ResumeLayout(false). Вызов mySubPanel.ResumeLayout() равен .ResumeLayout(true), что означает, что он должен немедленно переразметить этот элемент управления (и все дочерние элементы управления, которые не приостановлены в этот момент).

Цитата MSDN: «Вызов метода ResumeLayout [без параметров] вызывает немедленный макет, если есть какие-либо ожидающие запросы макета». [1]

Если вы хотите добавить 100 элементов управления на панель, вы хотите использовать такой подход:

  1. mainPanel.SuspendLayout()
  2. создать дочерний элемент управления
  3. вызовите child.SuspendLayout()
  4. изменить свойства дочернего элемента управления
  5. добавить дочерний элемент управления в mainPanel
  6. вызовите child.ResumeLayout(false) - это означает: следующий запуск макета, ретрансляция этого элемента управления, но не сразу
  7. повторите (2-6) для каждого дочернего элемента управления
  8. call mainPanel.ResumeLayout(true) - это означает: ретранслировать мою mainPanel и каждый дочерний элемент управления сейчас!

Примечание: без SuspendLayout() каждое изменение свойства элемента управления вызывало бы процедуру компоновки — даже изменение .BackColor приводит к изменению макета вашего элемента управления.

[1] http://msdn.microsoft.com/en-us/library/y53zat12.aspx

person toong    schedule 23.08.2013
comment
Это особенно помогает, если мы перебираем (цикл) множество элементов управления для изменения свойств. Отлично влияет на корпус петли. Спасибо! - person rajkumaradass; 27.02.2017