TThread.Synchronize 在 Delphi 2009 中导致(接近)死锁(在 Delphi 7 中工作)

发布于 2024-12-09 14:51:38 字数 739 浏览 0 评论 0原文

在 Delphi 2009 中,在 Delphi 7 中运行良好的同步函数执行速度极其缓慢,直到您在打开的窗体上移动鼠标为止。摆动鼠标会导致程序进入某种鼠标空闲状态,从而执行 CheckSynchronize()CheckSynchronize() 在 Delphi 2009 中的调用频率似乎低于在 Delphi 7 中的频率,但我们无法弄清楚原因或位置。

放置此代码:

    procedure TMyForm.FormCreate(Sender : TObject)
       Classes.WakeMainThread := WakeMainThread;
    end;

    procedure TMyForm.WakeMainThread(Sender: TObject);
    begin 
      SendMessage(Application.MainForm.Handle, WM_NULL, 0, 0);
    end;

以正常速度加快速度。但是,如果在模态应用程序中使用线程,则当线程终止时,我会得到: EAccessViolation in module rtl120.bpl (对于简单的对话框实用程序来说效果很好)。我猜测“Classes.WakeMainThread()”的调用次数与 Delphi 7 中的调用次数一样多,但是将 WM_NULL 发送到 application.handle 并没有完成任何操作。我想是时候“迈出步伐”了。

In Delphi 2009, synchronize'd functions that worked fine in Delphi 7 execute with sublime slowness until you wiggle the mouse over the open form. Wiggling the mouse causes the program to go into some mouse idle state which does CheckSynchronize(). CheckSynchronize() appears to be called less frequently in Delphi 2009 than in Delphi 7, but we can't figure out why or where.

Placing this code:

    procedure TMyForm.FormCreate(Sender : TObject)
       Classes.WakeMainThread := WakeMainThread;
    end;

    procedure TMyForm.WakeMainThread(Sender: TObject);
    begin 
      SendMessage(Application.MainForm.Handle, WM_NULL, 0, 0);
    end;

Speeds things along at the normal rate. But I get: EAccessViolation in module rtl120.bpl when the thread dies if it's used in a modal app (works fine for a simple dialog utility). I'm guessing 'Classes.WakeMainThread()' is being called just as much as it is in Delphi 7, but sending WM_NULL to application.handle isn't accomplishing anything. I guess it's time to 'get steppin'.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

油焖大侠 2024-12-16 14:51:38

Synchronize() 机制的内部结构在 D7 和 D2009 之间没有太大变化。当然,添加了新功能(异步队列、匿名方法等),但在主线程中运行代码的核心实现没有改变。更可能发生的情况是主线程代​​码中尚未显示的其他内容正在阻止主线程正确处理待处理消息和 Synchronize() 请求。

The internals of the Synchronize() mechanism have not changed much between D7 and D2009. Sure, there have been new features added (asynchronous queuing, anonymous methods, etc), but the core implementation to run code in the main thread has not changed. What is more likely happening is something else in your main thread code that you have not shown yet is blocking the main thread from processing pending messages and Synchronize() requests correctly.

好听的两个字的网名 2024-12-16 14:51:38

TApplication.Create 正在从另一个 DLL 中调用,因此它会唤醒无效句柄或该回调中的一些废话。

您需要消除包含 [vcl.]controls.pas 的静态链接 DLL,因为 TApplication.Create 发生在该单元的某些初始化代码中。

一旦执行此操作,同步将恢复到以前的辉煌。

不幸的是,您在一个版本的 Delphi 中所做的修复可能会因在另一版本的 Delphi 中所做的更改而被撤销。因此,如果问题再次出现,请重新开始。单步执行初始化代码,特别是 system.pas 中的 initUnits 过程。它运行初始化代码并最终会遇到 vcl.controls.pas,您可以查看 UnitInfo 记录以找出从哪个文件调用它。


解决此问题的最佳方法是对所有外部 dll(至少是所有 Delphi VCL 外部 DLL)使用delayed

 function didntknowIusedcontrolsbutIdo() : Integer; external 'useful.dll' delayed;

但这仅适用于 Delphi 2010 及更高版本。幸好您在提出这个问题和最终找到满意答案之间升级到了 XE2。

TApplication.Create is getting called from another DLL, hence it is waking an invalid handle or some nonsense in that callback.

You need to eliminate statically linked DLLs that include [vcl.]controls.pas because TApplication.Create happens in some initialization code in that unit.

Once you do this, synchronize will be restored to it's former glory.

Unfortunately, fixes you make in one version of Delphi might be undone by changes made in another version of Delphi. So if the problem comes back, go back to the drawing board. Step through the initialization code, specifically the initUnits procedure in system.pas. It runs the initialization code and will bump into vcl.controls.pas eventually and you can peer into the UnitInfo record to find out which file this is being called from.


The best way to fix this is to use the delayed with all your external dlls (at least all your Delphi VCL external DLLs).

 function didntknowIusedcontrolsbutIdo() : Integer; external 'useful.dll' delayed;

But this only works in Delphi 2010 and up. Good thing you upgraded to XE2 between the time you asked this question and the time you finally find a satisfying answer to it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文