简体   繁体   English

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

[英]TThread.Synchronize causing (near) deadlock in Delphi 2009 (worked in Delphi 7)

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. 在Delphi 2009中,在Delphi 7中正常工作的同步函数以崇高的速度执行,直到您在打开的表单上摆动鼠标。 Wiggling the mouse causes the program to go into some mouse idle state which does CheckSynchronize() . 摆动鼠标会导致程序进入某些鼠标空闲状态,并执行CheckSynchronize() CheckSynchronize() appears to be called less frequently in Delphi 2009 than in Delphi 7, but we can't figure out why or where. 在Delphi 2009中, CheckSynchronize()调用次数似乎比在Delphi 7中少,但我们无法弄清楚为什么或在哪里。

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). 但是我得到:当EAccessViolation in module rtl120.bpl ,如果它在一个模态应用程序中使用它就会死掉(适用于简单的对话框实用程序)。 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. 我猜测'Classes.WakeMainThread()'的调用与在Delphi 7中一样多,但是将WM_NULL发送到application.handle并没有完成任何事情。 I guess it's time to 'get steppin'. 我想是时候'踩到'了。

The internals of the Synchronize() mechanism have not changed much between D7 and D2009. Synchronize()机制的内部在D7和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. 更可能发生的是您的主线程代码中尚未显示的其他内容阻止主线程正确处理挂起的消息和Synchronize()请求。

TApplication.Create is getting called from another DLL, hence it is waking an invalid handle or some nonsense in that callback. TApplication.Create是从另一个DLL调用的,因此它唤醒了一个无效句柄或该回调中的一些废话。

You need to eliminate statically linked DLLs that include [vcl.]controls.pas because TApplication.Create happens in some initialization code in that unit. 您需要消除包含[vcl。] controls.pas的静态链接DLL,因为TApplication.Create发生在该单元的某些初始化代码中。

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. 遗憾的是,您在一个版本的Delphi中进行的修复可能会被另一个版本的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. 逐步执行初始化代码,特别是system.pas中的initUnits过程。 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. 它运行初始化代码并最终进入vcl.controls.pas,您可以UnitInfo记录以找出调用它的文件。


The best way to fix this is to use the delayed with all your external dlls (at least all your Delphi VCL external DLLs). 解决这个问题的最好方法是使用delayed的所有外部dll(至少所有的Delphi VCL外部DLL)。

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

But this only works in Delphi 2010 and up. 但这仅适用于Delphi 2010及更高版本。 Good thing you upgraded to XE2 between the time you asked this question and the time you finally find a satisfying answer to it. 在您提出此问题的时间与您最终找到满意答案的时间之间升级到XE2的好事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM