同步的 VB6 显然是异步的!碰撞
Synchronous VB6 apparently behaving asynchronously! Crash
我们有一个遗留的 VB6 应用程序已经启动,有时会挂起。我们认为这可能与转向 Citrix 有关,但现在可以在 Win10 的胖客户端上复制该行为。我们不认为我们之前在早期的 Windows 版本中看到过这种情况,但仍在检查日志以确认这一点。
我们在按 Tab 键进入文本框然后再按 Tab 键退出时遇到这种行为。当我们通过它时,我们正在对文本框中的一些数据进行简单的 ado 调用 lookup/validate 。作为正确程序的一部分 运行 我们正在记录
“Opening Dataset: SELECT ... FROM ... ”
“Opened Dataset”
在这 2 个日志语句之间是简单的 ado 数据检索代码,我们以前没有遇到过问题。它在一个 ActiveX dll 中并且是 运行 同步。最重要的是,在这两个日志语句之间,没有 DoEvents
或 api 调用会产生控制权。据我们所见,应该是纯同步操作。
当系统崩溃时,这偶尔会发生,我们可以看到其他日志记录语句出现在这两个之间,它们可以是资源状态(例如,多少内存,gdi/user 对象 - 通常可以找到,因为计时器已在主窗体中触发)或焦点类型事件——它们不是计时器驱动的——至少在我们的代码库中是这样。
“Opening Dataset: SELECT ... FROM ... ”
“Resource Status: ...”
“Opened Dataset”```
或
“Opening Dataset: SELECT ... FROM ... ”
“TextItem.OnLostFocus Item1 ...”
“TextItem.Validate ...”
“TextItem.OnGotFocus Item2 ...
“Opened Dataset”
所以我最初的问题是,在什么情况下本应同步的操作会被打断并表现为异步操作。
例如,我们没有这样做,我可以想象编写一些不安全的代码,通过使用多媒体计时器(在另一个线程上)并为我们的一个模块上的函数地址提供 AddressOf 参数,该计时器启动我们代码的执行,与正确的控制流分开。除了类似的东西,我只是看不出如何以这种方式中断同步 vb6 代码。
如果有任何想法、建议或建议,我将不胜感激。如果这太含糊了,我真的很抱歉。这也许反映了我是如何努力解决这个问题的。
只是说,我们追踪到 Windows 10 加上我们正在使用的旧(不受支持)套接字组件。它看起来像是“在错误的时间”发送消息队列,因此我们看到 UI 事件出现在同步进程的中间。我们在早期的 Windows 版本中没有看到这种行为。
我不知道 Win10 中可能发生了什么变化会导致这种情况,但我们显然需要升级。
在我们的例子中,我们有几个长 运行 计时器从数据库中提取 status/changes,这导致了这种情况。我们将 ADO 与 SQL Native Client 和 MARS 一起使用,在 Windows 10 出现间歇性锁定之前一直运行良好。日志记录和 Windbg 确认当 2 个请求同时命中 ADO 连接时会发生这种情况。 ADO 的错误是“无法打开逻辑会话”错误编号 -2147467259,实际上导致 SQL Server 2014(运行 在另一台机器上)阻止来自多个不同应用程序和机器的所有其他客户端查询直到锁定的应用程序被杀死。我无法在 IDE 中复制它,因为这显然会迫使计时器像往常一样工作。解决方法是异步我们的 ADO 实现,并在 SQL 连接之上放置一个连接管理器,以强制请求者等待轮到他们(基本上取消 Win10 异步计时器功能)。我唯一的性能影响是在与另一个查询冲突时延迟触发 SQL 查询的额外几毫秒。
我们有一个遗留的 VB6 应用程序已经启动,有时会挂起。我们认为这可能与转向 Citrix 有关,但现在可以在 Win10 的胖客户端上复制该行为。我们不认为我们之前在早期的 Windows 版本中看到过这种情况,但仍在检查日志以确认这一点。
我们在按 Tab 键进入文本框然后再按 Tab 键退出时遇到这种行为。当我们通过它时,我们正在对文本框中的一些数据进行简单的 ado 调用 lookup/validate 。作为正确程序的一部分 运行 我们正在记录
“Opening Dataset: SELECT ... FROM ... ”
“Opened Dataset”
在这 2 个日志语句之间是简单的 ado 数据检索代码,我们以前没有遇到过问题。它在一个 ActiveX dll 中并且是 运行 同步。最重要的是,在这两个日志语句之间,没有 DoEvents
或 api 调用会产生控制权。据我们所见,应该是纯同步操作。
当系统崩溃时,这偶尔会发生,我们可以看到其他日志记录语句出现在这两个之间,它们可以是资源状态(例如,多少内存,gdi/user 对象 - 通常可以找到,因为计时器已在主窗体中触发)或焦点类型事件——它们不是计时器驱动的——至少在我们的代码库中是这样。
“Opening Dataset: SELECT ... FROM ... ”
“Resource Status: ...”
“Opened Dataset”```
或
“Opening Dataset: SELECT ... FROM ... ”
“TextItem.OnLostFocus Item1 ...”
“TextItem.Validate ...”
“TextItem.OnGotFocus Item2 ...
“Opened Dataset”
所以我最初的问题是,在什么情况下本应同步的操作会被打断并表现为异步操作。
例如,我们没有这样做,我可以想象编写一些不安全的代码,通过使用多媒体计时器(在另一个线程上)并为我们的一个模块上的函数地址提供 AddressOf 参数,该计时器启动我们代码的执行,与正确的控制流分开。除了类似的东西,我只是看不出如何以这种方式中断同步 vb6 代码。
如果有任何想法、建议或建议,我将不胜感激。如果这太含糊了,我真的很抱歉。这也许反映了我是如何努力解决这个问题的。
只是说,我们追踪到 Windows 10 加上我们正在使用的旧(不受支持)套接字组件。它看起来像是“在错误的时间”发送消息队列,因此我们看到 UI 事件出现在同步进程的中间。我们在早期的 Windows 版本中没有看到这种行为。
我不知道 Win10 中可能发生了什么变化会导致这种情况,但我们显然需要升级。
在我们的例子中,我们有几个长 运行 计时器从数据库中提取 status/changes,这导致了这种情况。我们将 ADO 与 SQL Native Client 和 MARS 一起使用,在 Windows 10 出现间歇性锁定之前一直运行良好。日志记录和 Windbg 确认当 2 个请求同时命中 ADO 连接时会发生这种情况。 ADO 的错误是“无法打开逻辑会话”错误编号 -2147467259,实际上导致 SQL Server 2014(运行 在另一台机器上)阻止来自多个不同应用程序和机器的所有其他客户端查询直到锁定的应用程序被杀死。我无法在 IDE 中复制它,因为这显然会迫使计时器像往常一样工作。解决方法是异步我们的 ADO 实现,并在 SQL 连接之上放置一个连接管理器,以强制请求者等待轮到他们(基本上取消 Win10 异步计时器功能)。我唯一的性能影响是在与另一个查询冲突时延迟触发 SQL 查询的额外几毫秒。