为什么我的 MFC 应用程序在与两个滚动条交互后挂起?

2024-01-27

我正在开发一个 MFC 应用程序(在 Win10 下运行),其中包含一个图形 CAD 样式编辑器窗口。编辑器窗口包含用户可以重新定位和配置的图标。

在包含许多元素的布局中,我们发现编辑器窗口可能会挂起长达 30 秒。这个问题是not当我们的大多数用户使用 Windows 7 时报告;看来Windows 10开始出现这种情况,但我还没有回到Win7确认。

触发挂起的确切操作顺序是:

  1. 水平滚动(使用水平滚动条)
  2. 垂直滚动(使用垂直滚动条)
  3. 应用程序挂起大约 20-30 秒,然后恢复

上述步骤的微小变化也会触发临时挂起;例如,使用鼠标按钮垂直滚动,然后使用滚动条水平滚动,也会触发挂起。

挂起或锁定总是会恢复。我还注意到 Windows 中的其他应用程序会暂时“冻结”(例如:我无法拖动窗口,并且 UI 更新变得非常慢,例如all发生此挂起时正在运行的应用程序)。

我不确定从哪里开始调试,因为我有一种感觉,这发生在操作系统级别;我的第一个猜测是开始分析不同的代码行,以针对导致延迟的确切操作系统调用,但我不确定如果导致挂起的元素不是我的函数调用中的函数调用,那么这种方法的效果如何。代码;例如,操作系统中的某些队列可能几乎已满,导致消息泵变慢,而没有任何特定的操作系统调用看起来很慢。

我的问题是:

  1. Windows 10 中是否有任何变化? CWnd 计数较大,这可能会与滚动交互导致挂起?
  2. 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++ 的唯一效果是减慢速度。


事实证明这是一个 Windows 操作系统问题。 Microsoft 支持提供了高级解释:较新的 Windows 功能正在干扰我的应用程序。

看来我的调查指向了正确的方向:ntdll.dll or dwm.exe是罪魁祸首,而不是我的可执行文件。

Spy++ 解决了我的问题,这一事实很能说明问题。这表明我们是not运行时遇到严格的性能限制,并且还表明这不是我的应用程序停滞;操作系统级别的某些东西正在干扰自身。

Microsoft 支持代表指示我使用 Windows ADK 中应用程序兼容性工具下包含的兼容性管理工具。使用此向导,我生成了一个 shim 数据库 (.sdb),其中包含以下问题的修复程序:滚动WindowsExFlags.

然后,我在提升的命令行中使用以下命令来安装 shim 数据库:

sdbinst -u <path to the sdb file>

来自微软支持:

原因是有许多子窗口需要滚动。当他们在 滚动后,DWM 必须更新每个窗口的内部数据 感动了。太多会导致 DWM 不堪重负。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我的 MFC 应用程序在与两个滚动条交互后挂起? 的相关文章

  • 本地推送通知到在应用程序内运行 JS 代码的 Win8 Live Tile

    我正在尝试将更新发送到我的应用程序的磁贴 当应用程序运行时 这可以正常工作 例如 当用户单击按钮时 我可以轻松地将磁贴更新通知发送到磁贴 我无法解决的是当应用程序无法运行时如何更新磁贴 我找到的唯一选择是使用以下命令从远程 Web 服务器拉
  • 如何在Windows上模拟socket.socketpair

    标准Python函数套接字 套接字对 https docs python org 3 library socket html socket socketpair不幸的是 它在 Windows 上不可用 从 Python 3 4 1 开始 我
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 如何在 Netbeans 中调试 Java Web 应用程序?

    我曾多次在 Netbeans 中调试 Java 桌面应用程序 但从未调试过 Java Web 应用程序 我尝试以同样的方式调试它 但它不起作用 我制作了一个index html网页 该页面上有一个 表格 用户提交表单后 请求将发送至 ser
  • 如何为最终用户方便地启动Java GUI程序

    用户想要从以下位置启动 Java GUI 应用程序Windows 以及一些额外的 JVM 参数 例如 javaw Djava util logging config file logging properties jar MyGUI jar
  • 使用 GDB 调试 Rust

    我知道调试 Rust这里有关于 Stack Overflow 的问题 我之前也在 Go 中使用过 GDB 然而 我遇到了一个问题 GDB 似乎无法找到调试符号 考虑这个复杂的程序main rs pub fn main println run
  • 混合 MFC 和 WPF:模态对话框

    我使用 C CLI 界面层将 C WPF 对话框添加到现有的 C MFC 应用程序 我一切正常 只是我遇到了形式问题 例如 MFC 应用程序使用 ShowDialog 显示 WPF 对话框 按预期工作 该 WPF 对话框显示使用 DoMod
  • Windows 目录永远不会包含临时文件的非 ASCII 字符?

    在 Windows 上使用 MinGW 7 3 0 由于 Windows 限制 Hunspell 无法从包含非 ASCII 字符的位置加载字典文件 我已经尝试了所有方法 1 现在我将文件复制到没有 ASCII 字符的路径 然后再将其交给 H
  • 如何向未知用户目录读取/写入文件?

    我正在尝试从用户目录 C Users USERNAME Test Source 读取和写入文件 但我未能成功找到任何有关如何自动检测用户名的资源 其中的 USERNAME上面的例子 或者无论如何 我可以让它读取和写入目录 而不需要知道用户名
  • 关闭有效句柄时,AppVerifier 报告“无效句柄 - 代码 c0000008”

    我有一个简单的测试程序 在运行时会失败并出现异常AppVerifier 程序重复STD INPUT HANDLE然后尝试使用关闭它CloseHandle 该程序运行良好 无需AppVerifier返回TRUE for CloseHandle
  • Java 应用程序可以检测到调试器已连接吗?

    我知道 jvm 启动选项可以让 jvm 等待附加调试器 这不是我在这里的意思 是否有可能从 Java 代码中也检测调试器的附件 以便我可以例如编写一个正在执行某些操作的 脚本 然后在某个时刻让我的应用程序等待调试器 不会 这些选项是 JVM
  • 尽管 if 语句,Visual Studio 仍尝试包含 Linux 标头

    我正在尝试创建一个强大的头文件 无需更改即可在 Windows 和 Linux 上进行编译 为此 我的包含内容中有一个 if 语句 如下所示 if defined WINDOWS include
  • Google Cloud SDK 无法安装“.exe;.bat;.com”不是可识别的命令

    我正在尝试在 Windows 10 笔记本电脑上安装 google cloud SDK 我尝试删除安装文件夹中的空格 并将路径添加到我的环境变量中 完整的错误是 Output folder C Users user Documents Do
  • 用于创建计划任务的 VBScript

    我正在尝试创建一个 VBScript 它创建一个批处理文件 然后创建一个计划任务来运行该批处理文件 到目前为止 我尝试过的所有操作都创建了批处理文件 但没有创建计划任务 并且我没有收到任何错误 这是我到目前为止所拥有的 Option Exp
  • Xcode - 调试视图层次结构

    我正在尝试调试应用程序的视图层次结构 Xcode 窗口的左侧窗格中出现了一个紫色的小方块 请参见屏幕截图 知道这个问题可能是什么吗 好吧 我找到了这个问题的根源 这是一个约束问题
  • Sencha Cmd 5 + Java 8 错误

    在我的 Windows 构建服务器上安装 Java 8 JDK 后 执行以下命令时遇到以下错误sencha命令 C gt sencha Error Registry key Software JavaSoft Java Runtime En
  • 如何迭代所有注册表项?

    我正在尝试迭代所有注册表项以查找 包含 并删除 jre1 5 0 14 值 有办法做到吗 下面的代码只是在特定键下找到jre1 5 0 14 我确实想迭代所有的键 顺便说一句 if 子句获取是否等于 jre1 5 0 14 但如果它包含 j
  • 将 kinit 与 keytab 文件一起使用时会发生什么

    希望对kinit和keytab文件的使用有更多的了解 例如 如果我已经为某个服务生成了一个密钥表文件 该服务通过以下方式注册到活动目录 ktpass mapuser to someuseraccount ktab k mykeytab a
  • SetWindowsHookEx 函数返回 NULL

    我正在研究 DLL 注入 但收到错误如下 挂接进程失败 87 参数不正确 目标进程和dll都是64位的 注入代码为 BOOL HookInjection TCHAR target TCHAR dll name https msdn micr

随机推荐

  • 指南针 SCSS 颜色代码小写

    在我的团队中 我们有相同版本的 Compass Compass 0 12 2 Alnilam 当 Compass 编译我的 SCSS 时 SCSS 中的颜色代码从大写 A0CAE3 更改为小写 a0cae3 只有我有这个问题 其他开发人员都
  • 为什么 Rust 编译器要求我限制泛型类型参数的生命周期(错误 E0309)?

    为什么 Rust 编译器会发出错误 要求我限制以下结构中泛型参数的生命周期 pub struct NewType lt a T gt x a T error E0309 the parameter type T may not live l
  • Android 推送通知的自定义声音不起作用 (FCM)

    我有使用云功能中的 FCM 工作的推送通知 这适用于 iOS 和 Android 并在 iOS 上显示相应的图标并播放自定义声音 除了 Android 的自定义声音外 一切正常 它只是播放默认声音 我创建了一个文件夹并将声音文件添加到其中
  • Marionette 布局和区域有什么区别?

    Marionette 提供了两个名为Regions http derickbailey github com backbone marionette marionette region and Layouts http derickbail
  • 如何解析以字符串形式给出的数学表达式并返回一个数字? [复制]

    这个问题在这里已经有答案了 Java 有没有办法从这个数学表达式中得到结果 String code 5 4 7 15 另一方面 解析算术表达式的最佳方法是什么 您可以将其传递给豆壳 http www beanshell org bsh In
  • 如何以本地用户身份(无管理员权限)在 Windows 上安装 NodeJS LTS

    我以简单用户身份使用 Windows 我没有任何管理员权限 并且想要安装 NodeJS LTS On the 下载站点 https nodejs org en download 我可以选择仅下载二进制文件node exe 其中不包括npm
  • 打开文件的命令按钮 - 位于同一单元格按钮中的文件路径对齐到

    我正在尝试获取一个可以分配给命令按钮的宏 我有多个按钮可以打开不同的文件 因此在每个单元格中我都包含不同的文件路径 目前 我的命令按钮正在寻找特定的单元格引用并打开该值 有什么方法可以让宏在与其对齐的单元格中查找值 我目前正在使用两个宏 一
  • 没有这样的目的地

    我在我的网站中使用 Stripe 方法 用户从我的网站购买产品并通过 stripe 完成付款 我想收取佣金并将剩余的钱发送给服务提供商 当我尝试在条纹中使用传输方法时 它会显示错误消息 message No such destination
  • 如何使用 jq 获取两个 JSON 数组的交集

    给定数组 X 和 Y 最好都作为输入 但否则 一个作为输入 另一个硬编码 如何使用 jq 输出包含两者共有的所有元素的数组 例如f 的值是多少 使得 echo 1 2 3 4 jq f 2 4 6 8 10 会输出 2 4 我尝试过以下方法
  • 你能在 jQuery 中扩展 val() 函数吗?

    有没有办法扩展 jQuery 中的 val 函数 基本上 我想要做的是如果有内容被动态输入到输入中 则设置一个类变量 通常会是这样的 var thisVal Hello World myInput val thisVal addClass
  • Javascript parseFloat 和 null

    我对 javascript 非常陌生 因为我目前正在 jQuery Mobile 中制作跨平台 Web 应用程序 我已经使用了 XML 解析到 HighCharts 图表的示例 但是当我在系列数据中遇到 null 时 它无法绘制任何线条并使
  • 颜色逐渐变化

    屏幕左上角的标志如何随着鼠标滑过而逐渐改变颜色 我认为它是用 jquery 完成的 如果您不知道代码 您能给我指点可以的教程吗 谢谢 http www shopdev co uk blog http www shopdev co uk bl
  • 即使进行所有优化,Android 模拟器也会出现延迟

    HAXM 启用版本 7 1 0 我验证了它在模拟器运行时正常工作 模拟器使用 Nvidia GPU 但在任何给定时间它仅使用最多 7 的 GPU 我有 27 3 1 的模拟器版本 最新 尝试过 x86 图像和 x86 x64 图像 我尝试过
  • 多个按钮上的 javascript 函数

    我有三个按钮 我希望它们在按下时改变颜色 并在再次按下时恢复为无颜色 我在 stackoverflow 上找到了这段代码 它几乎可以让我做到这一点 但是它只适用于一个按钮 其他两个不受影响 另外 当我按下另外两个按钮中的一个时 第一个按钮会
  • 如何在 mongodb 中更新多个数组元素

    我有一个 Mongo 文档 其中包含一个元素数组 我想重置 handled数组中所有对象的属性 其中 profile XX 该文件的形式如下 id ObjectId 4d2d8deff4e6c1d71fc29a07 user id 7146
  • 发帖后查看未更新

    我有一个控制器方法 CreateOrUpdate 该方法应该将汽车保存到数据库 然后正常返回 public ActionResult CreateOrUpdate int ID 0 Car car new Car ID HttpPost p
  • 如何测试 JSONObject 是否为空或不存在

    我有一套JSONObject我从服务器接收并操作的值 大多数时候我得到一个JSONObject带有一个值 比如说统计数据 有时 它返回一个Error带有代码和错误描述的对象 如何构建我的代码 使其在返回错误时不会中断 我以为我可以做到这一点
  • 非规范化是为了理智还是为了性能?

    我开始了一个新项目 他们有一个非常标准化的数据库 所有可以查找的内容都存储为查找表的外键 这是规范化的并且很好 但我最终为最简单的查询执行了 5 个表连接 from va in VehicleActions join vat in Vehi
  • 未找到 Laravel Passport 安装类

    我正在尝试配置我的 Laravel 应用程序以使用 Passport 但在加载 AppServiceProvider php 中的类时遇到了困难 这是我所做的
  • 为什么我的 MFC 应用程序在与两个滚动条交互后挂起?

    我正在开发一个 MFC 应用程序 在 Win10 下运行 其中包含一个图形 CAD 样式编辑器窗口 编辑器窗口包含用户可以重新定位和配置的图标 在包含许多元素的布局中 我们发现编辑器窗口可能会挂起长达 30 秒 这个问题是not当我们的大多