Delphi点滴

作者:邹飞
E-mail:
zouf.tech@ATechSoft.com
Homepage:http://www.atechsoft.com/people/zouf/

 

 

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

如果

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

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

 

沟通创造一切

正文

 

Q: DelphiDLL中制作的Form,如果在ExeShowModal时,会在任务栏上出现两个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

解决方法:

在主应用程序中将主EXEApplication传入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中的ApplicationEXE中的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编译器的内存管理机制,和WindowsDLL/卸载机制,导致了DLLEXE中的内存存取冲突。

 

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

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

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

x := TClass.Create(nil);

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

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

3.其他

                                                                                                             

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

A:

解决方法一:

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

通过KillThread来结束线程。

这是最简单的方法,但也太粗暴,可能会导致问题(KillThreadWindows不推荐使用的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;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
探索全栈前端技术的魅力:HTML+CSS+JS+JQ+Bootstrap网站源码深度解析 在这个数字化时代,构建一个既美观又功能强大的网站成为了许多开发者和企业追逐的目标。本份资源精心汇集了一套完整网站源码,融合了HTML的骨架搭建、CSS的视觉美化、JavaScript的交互逻辑、jQuery的高效操作以及Bootstrap的响应式设计,全方位揭秘了现代网页开发的精髓。 HTML,作为网页的基础,它构建了信息的框架;CSS则赋予网页生动的外观,让设计创意跃然屏上;JavaScript的加入,使网站拥有了灵动的交互体验;jQuery,作为JavaScript的强力辅助,简化了DOM操作与事件处理,让编码更为高效;而Bootstrap的融入,则确保了网站在不同设备上的完美呈现,响应式设计让访问无界限。 通过这份源码,你将: 学习如何高效组织HTML结构,提升页面加载速度与SEO友好度; 掌握CSS高级技巧,如Flexbox与Grid布局,打造适应各种屏幕的视觉盛宴; 理解JavaScript核心概念,动手实现动画、表单验证等动态效果; 利用jQuery插件快速增强用户体验,实现滑动效果、Ajax请求等; 深入Bootstrap框架,掌握移动优先的开发策略,响应式设计信手拈来。 无论是前端开发新手渴望系统学习,还是资深开发者寻求灵感与实用技巧,这份资源都是不可多得的宝藏。立即深入了解,开启你的全栈前端探索之旅,让每一个网页都成为技术与艺术的完美融合!
探索全栈前端技术的魅力:HTML+CSS+JS+JQ+Bootstrap网站源码深度解析 在这个数字化时代,构建一个既美观又功能强大的网站成为了许多开发者和企业追逐的目标。本份资源精心汇集了一套完整网站源码,融合了HTML的骨架搭建、CSS的视觉美化、JavaScript的交互逻辑、jQuery的高效操作以及Bootstrap的响应式设计,全方位揭秘了现代网页开发的精髓。 HTML,作为网页的基础,它构建了信息的框架;CSS则赋予网页生动的外观,让设计创意跃然屏上;JavaScript的加入,使网站拥有了灵动的交互体验;jQuery,作为JavaScript的强力辅助,简化了DOM操作与事件处理,让编码更为高效;而Bootstrap的融入,则确保了网站在不同设备上的完美呈现,响应式设计让访问无界限。 通过这份源码,你将: 学习如何高效组织HTML结构,提升页面加载速度与SEO友好度; 掌握CSS高级技巧,如Flexbox与Grid布局,打造适应各种屏幕的视觉盛宴; 理解JavaScript核心概念,动手实现动画、表单验证等动态效果; 利用jQuery插件快速增强用户体验,实现滑动效果、Ajax请求等; 深入Bootstrap框架,掌握移动优先的开发策略,响应式设计信手拈来。 无论是前端开发新手渴望系统学习,还是资深开发者寻求灵感与实用技巧,这份资源都是不可多得的宝藏。立即深入了解,开启你的全栈前端探索之旅,让每一个网页都成为技术与艺术的完美融合!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值