Я работаю над приложением MF C (работающим под Win10), которое включает в себя окно графического редактора в стиле CAD. Окно редактора содержит значки, которые пользователь может перемещать и настраивать.
В макетах со многими элементами мы обнаруживаем, что окно редактора может зависать до 30 секунд. Эта проблема была , а не , когда большинство наших пользователей были на Windows 7; похоже, это начало происходить с Windows 10, но я не вернулся к Win7, чтобы подтвердить.
Точная последовательность действий, вызывающих зависание:
- Прокрутка по горизонтали (с помощью горизонтальной полосы прокрутки)
- Прокрутка по вертикали (с использованием вертикальной полосы прокрутки) )
- Приложение зависает примерно на 20-30 секунд, затем восстанавливает
Незначительные изменения описанных выше шагов также вызывают временное зависание; например, вертикальная прокрутка с помощью кнопки мыши, а затем горизонтальная прокрутка с помощью полосы прокрутки также вызывает зависание.
Зависание или блокировка всегда восстанавливается. Я также заметил, что другие приложения в Windows временно «зависли» (например: я не могу перетаскивать окно, и обновления пользовательского интерфейса становятся очень медленными, для всех приложений, работающих при этом зависании ).
Я не уверен, с чего начать отладку, потому что у меня такое чувство, что это происходит на уровне ОС; Моим первым предположением было бы начать профилирование различных строк кода, чтобы нацелиться на точный вызов ОС, вызывающий задержку, но я не уверен, насколько хорошо этот подход будет работать, если элемент, вызывающий зависание, является чем-то отличным от вызова функции в моем код; например, может быть, какая-то очередь почти заполнена в ОС, что приводит к замедлению работы сервера сообщений без какого-либо конкретного вызова ОС, который кажется медленным
Мои вопросы:
- Есть ли какие-либо изменения в Windows 10 относительно большого количества CWnd, которые могут взаимодействовать с прокруткой, вызывая зависание?
- Какие инструменты Windows предоставляет для отладки этого сценария? Должен ли я смотреть на WinDbg? Должен ли я сосредоточиться на профилировании проблемы без использования специальных средств отладки?
Я собираюсь работать над этой проблемой с точки зрения внутреннего приложения (чтобы исключить возможность того, что наш код напрямую вызывая зависание), но я был бы признателен за любые рекомендации по наилучшему подходу к устранению этой проблемы, предполагая, что в нашем коде нет ничего очевидного, например, 30-секундный вызов функции.
Спасибо для комментариев. Вот некоторая новая информация:
- Низкое использование процессора во время этого события; колеблется в пределах 1-3%, поэтому мой код не является узким местом ЦП.
- Я добавил операторы TRACE в свои обработчики HSCROLL и VSCROLL как в точке входа, так и в точке выхода. Кажется, что зависание происходит до входа в мой обработчик VSCROLL, сразу после нажатия левой кнопкой мыши на полосу прокрутки.
- Код имеет обработчик для LButtonDown, но он делает Похоже, что при нажатии на полосу прокрутки не ударил
- Приложение имеет 208 объектов GDI и 66 объектов пользователя, поэтому я думаю, что мы значительно ниже предела
- Эта проблема наблюдалась на все протестированные ПК с Win10, он не уникален для одной машины
Собираюсь сейчас попробовать Spy ++.
Я не вижу каких-либо очевидных проблем с обработчиками и выводом отладки кажется, исключает их как виновника, но здесь они для полноты:
void CDrawing60View::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
TRACE("OnHScroll:Begin\r\n");
int i = 1;
switch ( nSBCode )
{
case SB_LEFT : // Scroll to far left.
i = 2 ;
break ;
case SB_ENDSCROLL : // End scroll.
i = 3 ;
break ;
case SB_LINELEFT : // Scroll left. left arrow on left side of scroll bar
i = 4 ;
break ;
case SB_LINERIGHT : // Scroll right. right arrow on right side of scroll bar
i = 5 ;
break ;
case SB_PAGELEFT : // Scroll one page left.
i = 6 ;
break ;
case SB_PAGERIGHT : // Scroll one page right.
i = 7 ;
break ;
case SB_RIGHT : // Scroll to far right.
i = 8 ;
break ;
case SB_THUMBPOSITION : // Scroll to absolute position. The current position is specified by the nPos parameter.
i = 9 ;
break ;
case SB_THUMBTRACK : // Drag scroll box to specified position.
i = 10;
break ;
}
CFormView::OnHScroll(nSBCode, nPos, pScrollBar);
CPoint p = GetScrollPosition(); // p = how much we have scrolled in the horizontal/vertical directions
SNAP_TO_8_PIXELS (p.x);
SNAP_TO_8_PIXELS ( p.y)
ScrollToPosition ( p ) ;
MoveDrawing . LastScrollPositionX = p . x ; // used when saving the drawing
MoveDrawing . LastScrollPositionY = p . y ;
TRACE("OnHScroll:End\r\n");
}
void CDrawing60View::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
TRACE("OnVScroll:Begin\r\n");
int i = 0;
switch ( nSBCode )
{
case SB_BOTTOM : // Scroll to bottom.
i = 2 ;
break ;
case SB_ENDSCROLL : // End scroll.
break ;
case SB_LINEDOWN : // Scroll one line down.
i = 2 ;
break ;
case SB_LINEUP : // Scroll one line up.
i = 2 ;
break ;
case SB_PAGEDOWN : // Scroll one page down.
i = 2 ;
break ;
case SB_PAGEUP : // Scroll one page up.
i = 2 ;
break ;
case SB_THUMBPOSITION : // Scroll to the absolute position. The current position is provided in nPos.
i = 2 ;
break ;
case SB_THUMBTRACK : // Drag scroll box to specified position. The current position is provided in nPos.
i = 2 ;
break ;
case SB_TOP : // Scroll to top.
i = 2 ;
break ;
}
CFormView::OnVScroll(nSBCode, nPos, pScrollBar);
CPoint p = GetScrollPosition(); // p = how much we have scrolled in the horizontal/vertical directions
SNAP_TO_8_PIXELS (p.x);
SNAP_TO_8_PIXELS ( p.y)
ScrollToPosition ( p ) ;
MoveDrawing . LastScrollPositionX = p . x ; // used when saving the drawing
MoveDrawing . LastScrollPositionY = p . y ;
TRACE("OnVScroll:End\r\n");
}
Хорошо, Spy ++ дал некоторые интересные результаты. Когда я запускаю Spy ++, я не могу воспроизвести эту проблему! . Интересно, предполагает ли это состояние гонки в моих обработчиках, потому что единственный эффект, который я могу себе представить в Spy ++, заключается в замедлении работы.