加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi 6 TWinControl后代的WndProc()有时会在主VCL线程中执行吗

发布时间:2020-12-15 09:24:49 所属栏目:大数据 来源:网络整理
导读:我有一个严重多线程的Delphi 6应用程序.我有一个我创建的组件,它来自TWinControl.当我第一次构建它时,我使用了一个隐藏窗口,它是WndProc来处理使用AllocateHwnd()分配的消息.最近我开始在我的代码中清理WndProc并决定删除辅助WndProc().我更改了组件以覆盖基
我有一个严重多线程的Delphi 6应用程序.我有一个我创建的组件,它来自TWinControl.当我第一次构建它时,我使用了一个隐藏窗口,它是WndProc来处理使用AllocateHwnd()分配的消息.最近我开始在我的代码中清理WndProc并决定删除辅助WndProc().我更改了组件以覆盖基类WndProc()方法,并从那里进行自定义窗口消息处理.在那个WndProc()中,我首先调用了继承的处理程序,然后处理了我的自定义消息(WM_USER偏移),如果找到我的一个自定义消息并将其处理,则将消息Result字段设置为1.

一个重要的说明.我在WndProc()覆盖的顶部放置了一行代码,如果当前线程id不是VCL主线程,则抛出异常.我想确保WndProc()仅在主VCL线程的上下文中执行.

在完成这个并运行我的程序后,我遇到了一些看起来很奇怪的东西.我正常运行我的程序并完成各种任务而没有错误.然后,当我转到与我的TWinControl后代位于同一页面的TMemo控件时.如果我在TMemo控件内部单击,则在我的WndProc()覆盖中触发主线程检查.我设置了断点,当我进入调用堆栈时,我的WndProc()覆盖上方没有任何内容.

据我所知,我已经仔细检查过,我没有明确调用WndProc()覆盖.那不是我做过的事.但鉴于我的TWinControl组件已经在主VCL线程上像所有其他组件一样创建,我无法理解WndProc()覆盖如何在后台线程的上下文中执行,尤其是在像UI这样的UI操作时鼠标点击会发生.我理解我的WndProc()是如何绑定到TMemo控件的,因为所有子窗口都挂在顶层窗口WndProc()上,至少这是我的理解.但是由于所有组件窗口都是在主VCL线程上创建的,那么它们的所有消息队列也应该在该上下文中执行,对吧?

那么我可以创建什么样的情况来使我的WndProc()运行,有时只在后台线程的上下文中运行?

解决方法

有两种方法可以在工作线程的上下文中调用主线程组件的WndProc()方法:

>工作线程直接调用组件的WindowProc属性或其Perform()方法.
>工作者线程通过不安全地使用TWinControl.Handle属性来窃取组件窗口的所有权. Handle属性getter不是线程安全的.如果工作线程在主线程重新创建组件窗口的同一时刻从Handle属性读取(TWinControl窗口不是持久的 – 各种运行时条件可以动态地重新创建它们而不影响大部分UI逻辑),那么存在一个竞争条件,可以允许工作线程在其自己的上下文中分配一个新窗口(并导致主线程泄漏另一个窗口).这将导致主线程停止在其上下文中接收和分派消息.如果工作线程有自己的消息循环,那么它将接收和分派消息,从而在错误的线程上下文中调用WndProc()方法.

但我觉得奇怪的是没有生成调用堆栈.应始终存在某种痕迹.

此外,请确保MainThreadId变量(或您用于跟踪主线程的任何内容)不会简单地被意外损坏.确保其当前值与启动时的初始值一致.

您应该做的另一件事是在调试器中命名所有线程实例(此功能是在Delphi 6中引入的).这样,当您的线程验证被触发时,调试器可以显示调用WndProc()方法的线程上下文的确切名称(即使没有调用堆栈跟踪),然后您可以在代码中查找错误线.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读