分享
 
 
 

Delphi点滴

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

作者:邹飞

E-mail:zouf.tech@ATechSoft.com

Homepage:http://www.atechsoft.com/people/zouf/

用Delphi的过程中难免会遇到很多奇怪的问题,而Delphi的文档也出奇的少,因此只能自己慢慢的总结,所以有了下文(由于只是零散的细节,所以文笔上没有花什么功夫,可能会比较乱,但应该能够理解;-))。

如果:

1. 你有下面问题的更好解决方法,请告诉我,和csdn上的朋友

2. 你有其他的问题,请列出问题,以及你的解答,告诉我,和csdn上的朋友。

沟通创造一切!

正文:

Q: 在Delphi的DLL中制作的Form,如果在Exe中ShowModal时,会在任务栏上出现两个Icon,为什么?如何解决这个问题?

A: 下面是一种典型的DLL中放Form的方法:

DLL:

function ShowFrm: TModalResult; stdcall;

begin

Form1 := TForm1.Create(Nil);

try

Form1.ShowModal;

finally

Form1.Free;

end;

end;

主EXE:

function ShowFrm: TModalResult; stdcall; external 'TestDLL.dll';

begin

ShowFrm;

end.

以这种方式做出的DLL中的Form,会和主应用程序显示另一个Icon,其原因在于:

Delphi中对于DLL会另外再创建一个Application,而每个Application都会显示一个任务栏的Icon。

解决方法:

在主应用程序中将主EXE的Application传入DLL,如下:

DLL:

function ShowFrm(app: TApplication): TModalResult; stdcall;

var

oldApp: TApplication;

begin

oldApp := Application;

Application := app;

Form1 := TForm1.Create(Nil);

try

Form1.ShowModal;

finally

Form1.Free;

end;

Application := oldApp;

end;

主EXE:

function ShowFrm(app: TApplication): TModalResult; stdcall; external 'TestDLL.dll';

begin

ShowFrm(Application);

end.

注:DLL中的Application和EXE中的Application还是有些区别的,看Forms.pas中的代码:

constructor TApplication.Create(AOwner: TComponent);

begin

if not IsLibrary then CreateHandle;

end;

可以知道,DLL中的Application没有Handle,因此不会进行消息循环处理,这也是很正确的。

Q: Delphi中的DLL,经常出现问题!

A: 至所以出现问题,是因为Delphi本身的内存管理机制。比如:

在DLL中创建一个对象:

x := TClass.Create(Application);

这时,Delphi会在Application Free时自动Free x,但由于x是在DLL的地址空间中,当Application结束时,DLL的地址空间可能已经失效(不同的操作系统会有不一样),因此这时对x的释放操作就会引发异常。

又比如:

在EXE中创建了一个对象,并且传入了DLL作为DLL中的局部变量,这样在DLL销毁时,由于Delphi会将所有超出作用域的变量自动释放,因此如果再在EXE中使用这个对象,就会引发异常。

总的说,问题是由于“聪明”的Delphi编译器的内存管理机制,和Windows的DLL加/卸载机制,导致了DLL和EXE中的内存存取冲突。

解决方法:(只要遵循以下几个原则就可以避免大多数的问题)

1.在DLL和EXE之间,尽量不要使用Delphi的自动内存管理机制,由程序员自己对对象的生命期负责,比如:

对于上面的x := TClass.Create(Application);把它改成:

x := TClass.Create(nil);

这样,Application就不会再Free它了。当然,程序员必须自己来释放它。

2.尽量避免在DLL和EXE之间存在不同的指针指向的同一个对象。比如,在DLL中有x指向TClass对象,在EXE中又有y指向TClass对象,这样在任何一边的内存释放都会导致另一边的内存无效。

3.其他…

Q: 一个做周期性任务的线程,在其中需要暂停片刻,然后继续运行,但如果这时需要让线程停止(比如进程已经结束了),那该怎么办?

A:

解决方法一:

在线程中通过Sleep进行周期循环。(如果在线程中通过Sleep暂停了,通过Resume等方法是无法使得线程重新复活的)

通过KillThread来结束线程。

这是最简单的方法,但也太粗暴,可能会导致问题(KillThread是Windows不推荐使用的API)

解决方法二:

在线程中Suspend,在线程外面通过一个定时器,每隔一段时间就Resume。代码如下:

// Thread

procedure Execute;

begin

while not Terminated do

begin

… // 处理代码

Suspend;

end;

end;

// 外面

// 定时器

procedure OnTimer(Sender: Tobject);

begin

thd.Resume;

end;

// 要结束线程的地方

thd.Resume;

thd.Terminate;

thd.WaitFor; // 一般在结束线程后得通过WaitFor确认线程已经真的结束了。

问题:线程和外部的耦合太强了,甚至线程的操作周期得通过外面的定时器来确定。

解决方法三(这是我想到的最好方法):

在线程中通过信号量进行暂停操作。

// Thread

TMyThread = class(TThread)

private

Event: TEvent;

protected

procedure Execute; override;

public

constructor Create(loginInfo: TLoginInfo); overload;

destructor Destroy; override;

procedure SetEvent;

end;

{ TMyThread }

constructor TMyThread.Create(loginInfo: TLoginInfo);

begin

Event := TEvent.Create(nil, True, True, 'EventName');

end;

destructor TMyThread.Destroy;

begin

Event.Free;

inherited;

end;

procedure TMyThread.Execute;

begin

inherited;

while not Terminated do

begin

// ...

Event.ResetEvent;

Event.WaitFor(10000);

end;

end;

procedure TMyThread.SetEvent;

begin

Event.SetEvent;

end;

对于需要中断线程的程序,只需如下代码即可:

begin

thd.Terminate;

thd.SetEvent;

thd.WaitFor;

end;

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有