在Delphi 2009中,在Delphi 7中运行良好的同步函数执行起来非常缓慢,直到您将鼠标移动到打开的窗体上。摆动鼠标导致程序进入鼠标空闲状态,这是CheckSynchronize()
。在Delphi 2009中,CheckSynchronize()
的调用次数似乎比在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到应用程序。Handle没有完成任何事情。我想是时候"行动起来"了。
Synchronize()
机制内部在D7和D2009之间没有太大变化。当然,增加了一些新特性(异步队列、匿名方法等),但在主线程中运行代码的核心实现并没有改变。更有可能发生的事情是主线程代码中还没有显示的其他东西阻止主线程正确处理挂起的消息和Synchronize()
请求。
TApplication。Create正在从另一个DLL中调用,因此它正在唤醒该回调中的无效句柄或一些无意义的内容。
您需要消除包含[vcl.]控件的静态链接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。