我正在开发一个 MFC 应用程序(在 Win10 下运行),其中包含一个图形 CAD 样式编辑器窗口。编辑器窗口包含用户可以重新定位和配置的图标。
在包含许多元素的布局中,我们发现编辑器窗口可能会挂起长达 30 秒。这个问题是not当我们的大多数用户使用 Windows 7 时报告;看来Windows 10开始出现这种情况,但我还没有回到Win7确认。
触发挂起的确切操作顺序是:
- 水平滚动(使用水平滚动条)
- 垂直滚动(使用垂直滚动条)
- 应用程序挂起大约 20-30 秒,然后恢复
上述步骤的微小变化也会触发临时挂起;例如,使用鼠标按钮垂直滚动,然后使用滚动条水平滚动,也会触发挂起。
挂起或锁定总是会恢复。我还注意到 Windows 中的其他应用程序会暂时“冻结”(例如:我无法拖动窗口,并且 UI 更新变得非常慢,例如all发生此挂起时正在运行的应用程序)。
我不确定从哪里开始调试,因为我有一种感觉,这发生在操作系统级别;我的第一个猜测是开始分析不同的代码行,以针对导致延迟的确切操作系统调用,但我不确定如果导致挂起的元素不是我的函数调用中的函数调用,那么这种方法的效果如何。代码;例如,操作系统中的某些队列可能几乎已满,导致消息泵变慢,而没有任何特定的操作系统调用看起来很慢。
我的问题是:
- Windows 10 中是否有任何变化? CWnd 计数较大,这可能会与滚动交互导致挂起?
- Windows 提供了哪些工具来调试这种情况?我应该看看 WinDbg 吗?我是否应该专注于分析问题而不使用任何专用调试工具?
我将从内部应用程序的角度来解决这个问题(以排除我们的代码直接导致挂起的可能性),但如果我们不这样做,我将不胜感激有关调试此问题的最佳方法的任何指导我们的代码中有一些明显的东西,比如 30 秒的函数调用。
谢谢你的意见。以下是一些新信息:
- 活动期间CPU使用率较低;徘徊在 1-3% 左右,所以我的代码没有受到 CPU 的瓶颈。
- 我在入口点和出口点将 TRACE 语句添加到 HSCROLL 和 VSCROLL 处理程序中。似乎正在发生挂起before用鼠标左键单击滚动条后立即进入我的 VSCROLL 处理程序。
- 该代码有一个 LButtonDown 的处理程序,但当单击滚动条时它似乎没有被点击
- 该应用程序有 208 个 GDI 对象和 66 个 User 对象,所以我认为我们远远低于限制
- 所有测试的 Win10 PC 上均观察到此问题,并非单机独有
现在要尝试 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++ 的唯一效果是减慢速度。