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

时间:2011-10-12 15:57:46

标签: multithreading delphi delphi-7 delphi-2009

在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发送到application.handle并没有完成任何事情。我想是时候'踩到'了。

2 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:4)

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

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

一旦你这样做,同步将恢复到昔日的辉煌。

不幸的是,您在一个版本的Delphi中进行的修复可能会被另一个版本的Delphi中的更改所取消。因此,如果问题再次出现,请返回绘图板。逐步执行初始化代码,特别是system.pas中的initUnits过程。它运行初始化代码并最终进入vcl.controls.pas,您可以查看UnitInfo记录以找出要调用的文件。


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

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

但这仅适用于Delphi 2010及更高版本。在您提出此问题的时间与您最终找到满意答案的时间之间升级到XE2的好事。