Windows 为什么我的MFC应用程序在与两个滚动条交互后挂起?
我正在开发一个MFC应用程序(在Win10下运行),其中包括一个图形化CAD样式编辑器窗口。编辑器窗口包含用户可以重新定位和配置的图标 在包含许多元素的布局中,我们发现编辑器窗口最多可以挂起30秒。当我们的大多数用户都在Windows 7上时,没有报告此问题;这似乎是Windows10开始出现的,但我还没有回到Win7来确认 触发挂起的确切操作顺序为:Windows 为什么我的MFC应用程序在与两个滚动条交互后挂起?,windows,debugging,mfc,Windows,Debugging,Mfc,我正在开发一个MFC应用程序(在Win10下运行),其中包括一个图形化CAD样式编辑器窗口。编辑器窗口包含用户可以重新定位和配置的图标 在包含许多元素的布局中,我们发现编辑器窗口最多可以挂起30秒。当我们的大多数用户都在Windows 7上时,没有报告此问题;这似乎是Windows10开始出现的,但我还没有回到Win7来确认 触发挂起的确切操作顺序为: 水平滚动(使用水平滚动条) 垂直滚动(使用垂直滚动条) 应用程序挂起约20-30秒,然后恢复 上述步骤的微小变化也会触发临时挂起;例如,使用鼠标
谢谢你的评论。以下是一些新信息:
- 此事件期间CPU使用率低;徘徊在1-3%左右,所以我的代码不会受到CPU的限制
- 我在入口点和出口点向HSCROLL和VSCROLL处理程序添加了跟踪语句。挂起似乎发生在输入我的VSCROLL处理程序之前,即用鼠标左键单击滚动条之后
- 该代码有一个用于LButtonDown的处理程序,但当单击滚动条时,它似乎没有被点击
- 该应用程序有208个GDI对象和66个用户对象,因此我认为我们远远低于限制
- 在所有已测试的Win10 PC上都观察到了此问题,它不是单一机器所独有的
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++的唯一效果是减慢速度。这是Windows操作系统的问题。Microsoft支持提供了一个高级解释:较新的Windows功能正在干扰我的应用程序 看来我的调查指向了正确的方向:
ntdll.dll
或dwm.exe
是罪魁祸首,而不是我的可执行文件
Spy++解决了我的问题,这一事实很能说明问题。这表明我们没有遇到严格的性能限制,也表明这不是我的应用程序停滞;操作系统级别的某些东西正在自我干扰
Microsoft支持代表指示我使用Windows ADK中“应用程序兼容性工具”下的“兼容性管理员”工具。使用此向导,我生成了一个垫片数据库(.sdb),其中包含对ScrollWindowsExFlags的修复
然后,我在提升的命令行中使用以下命令来安装垫片数据库:
sdbinst -u <path to the sdb file>
sdbinst-u
来自Microsoft支持:
有许多子窗口可滚动是原因。当他们
滚动时,DWM必须更新每个窗口的内部数据
感动的它们太多了,让DWM不知所措
>>我还注意到,Windows中的其他应用程序会暂时“冻结”(例如:对于发生此挂起时运行的所有应用程序,我无法拖动窗口,UI更新会变得非常慢)。这可能意味着您的应用程序占用了大量CPU时间,请在task manager中查看CPU使用情况。如果是这样的话,那么研究代码中的哪些函数会导致这种情况。可能会考虑发布(一些)处理滚动请求的代码:在<代码> HRONG和<代码> VRONG处理程序之间可能会发生无意间的数据竞争。在Windows 10中,我还没有看到这种冻结问题。您的Windows设置可能有问题,或者您正在运行资源密集型应用程序。使用任务管理器检查应用程序使用了多少GDI句柄,或者其他应用程序是否正在使用资源。某些Windows后台任务(Defender、Cortana、User Experience等)确实会导致UI延迟,并使系统看起来冻结。也许可以检查一下这些是否会干扰你,给你带来麻烦。对于应用程序,上面@AdrianMole的评论可能就是答案。使用跟踪(非调试)t