Спасибо всем, кто ответил. Я слишком усложнял вещи в надежде улучшить отзывчивость, но только ухудшал положение. У меня были отдельные подпрограммы для обработки изменений на экранном элементе и для перерисовки экрана. Для каждого элемента я сохранял объекты, представляющие текущее состояние, состояние, отображаемое на экране, и состояние, отображаемое в фоновом растровом изображении. Когда элемент, который уже был нарисован на экране, изменился, я бы нарисовал измененную версию прямо на экране (используя Control.CreateGraphics), ничего не отменяя. Когда часть экрана была признана недействительной и нуждалась в перерисовке, я обновлял элементы на резервной битовой карте, а затем копировал фоновую битовую карту на экран. Моя цель состояла в том, чтобы избежать копирования всего растрового изображения на экран при каждом изменении элемента. Я ожидал, что перерисовки экрана из-за аннулирования области обычно не будут чередоваться с обновлениями элементов, и что обновление элемента путем рисования на экране будет быстрее, чем рисование в закадровом растровом изображении и копирование этого на экран.
Производительность значительно улучшилась, когда я заставил код с измененным элементом нарисовать изображение за пределами экрана и сделать недействительной область, содержащую элемент. Кажется, что при копировании растровых изображений на экран существует существенный штраф за каждую операцию рисования, которого нет при копировании в другое закадровое растровое изображение. Таким образом, копирование двадцати маленьких растровых изображений в большие куски, аннулирование областей экранного представления, где появляются эти маленькие растровые изображения, и затем копирование всего большого растрового изображения на экран (обрезанное по недействительным областям) намного быстрее, чем просто бросая маленькие растровые изображения на экране.