TThread.Synchronize在Delphi 2009中导致(接近)死锁(在Delphi 7中工作) [英] TThread.Synchronize causing (near) deadlock in Delphi 2009 (worked in Delphi 7)

查看:465
本文介绍了TThread.Synchronize在Delphi 2009中导致(接近)死锁(在Delphi 7中工作)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Delphi 2009中,在Delphi 7中运行正常的同步功能可以以极高的速度执行,直到将鼠标悬停在打开的窗体上。摆动鼠标会导致程序进入某些鼠标空闲状态,而 CheckSynchronize()。在Delphi 2009中,与Delphi 7相比,CheckSynchronize()似乎不太频繁,但是我们无法弄清楚为什么或在哪里。



放置此代码:

 过程TMyForm.FormCreate(发件人:TObject)
Classes.WakeMainThread := WakeMainThread;
结束

程序TMyForm.WakeMainThread(Sender:TObject);
begin
SendMessage(Application.MainForm.Handle,WM_NULL,0,0);
结束

以正常速度加速事情。但是当线程在模态应用程序中使用时,如果线程死机,则会在模块rtl120.bpl 中获得以下内容: EAccessViolation(适用于简单的对话框实用程序)。我猜测'Classes.WakeMainThread()'被调用与Delphi 7一样多,但是发送WM_NULL到application.handle并没有完成任何事情。我想是时候获得步兵了。

解决方案

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



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



一旦你这样做,同步将恢复到以前的荣耀。



不幸的是,您在一个版本的Delphi中进行的修复可能会被另一个版本的Delphi所做的更改所取消。所以如果问题回来了,回到绘图板。通过初始化代码,特别是system.pas中的 initUnits 过程。它运行初始化代码,最终会碰到vcl.controls.pas,您可以同步到 UnitInfo 记录中,以查找正在调用哪个文件。






解决此问题的最佳方法是使用延迟的与所有的外部DLL(至少所有的Delphi VCL外部DLL)。

  function didntknowIusedcontrolsbutIdo():Integer;外部有用的DLL延迟; 

但这只适用于Delphi 2010及以上版本。在你问这个问题的时候和你终于找到一个令人满意的答案的时候,你升级到XE2的好东西。


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'.

解决方案

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.

这篇关于TThread.Synchronize在Delphi 2009中导致(接近)死锁(在Delphi 7中工作)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆