国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Delphi > 正文

Delphi點(diǎn)滴

2019-11-18 18:25:42
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
 
 
用Delphi的過(guò)程中難免會(huì)遇到很多奇怪的問(wèn)題,而Delphi的文檔也出奇的少,因此只能自己慢慢的總結(jié),所以有了下文(由于只是零散的細(xì)節(jié),所以文筆上沒(méi)有花什么功夫,可能會(huì)比較亂,但應(yīng)該能夠理解;-))。
如果:
1. 你有下面問(wèn)題的更好解決方法,請(qǐng)告訴我,和csdn上的朋友
2. 你有其他的問(wèn)題,請(qǐng)列出問(wèn)題,以及你的解答,告訴我,和csdn上的朋友。
 
溝通創(chuàng)造一切!

正文:
 
Q: 在Delphi的DLL中制作的Form,如果在Exe中ShowModal時(shí),會(huì)在任務(wù)欄上出現(xiàn)兩個(gè)Icon,為什么?如何解決這個(gè)問(wèn)題?
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,會(huì)和主應(yīng)用程序顯示另一個(gè)Icon,其原因在于:
Delphi中對(duì)于DLL會(huì)另外再創(chuàng)建一個(gè)application,而每個(gè)Application都會(huì)顯示一個(gè)任務(wù)欄的Icon。
解決方法:
在主應(yīng)用程序中將主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還是有些區(qū)別的,看Forms.pas中的代碼:
constructor TApplication.Create(AOwner: TComponent);
begin
if not IsLibrary then CreateHandle;
end;
可以知道,DLL中的Application沒(méi)有Handle,因此不會(huì)進(jìn)行消息循環(huán)處理,這也是很正確的。
 
Q: Delphi中的DLL,經(jīng)常出現(xiàn)問(wèn)題!
A: 至所以出現(xiàn)問(wèn)題,是因?yàn)镈elphi本身的內(nèi)存管理機(jī)制。比如:
在DLL中創(chuàng)建一個(gè)對(duì)象:
x := TClass.Create(Application);
這時(shí),Delphi會(huì)在Application Free時(shí)自動(dòng)Free x,但由于x是在DLL的地址空間中,當(dāng)Application結(jié)束時(shí),DLL的地址空間可能已經(jīng)失效(不同的操作系統(tǒng)會(huì)有不一樣),因此這時(shí)對(duì)x的釋放操作就會(huì)引發(fā)異常。
又比如:
在EXE中創(chuàng)建了一個(gè)對(duì)象,并且傳入了DLL作為DLL中的局部變量,這樣在DLL銷(xiāo)毀時(shí),由于Delphi會(huì)將所有超出作用域的變量自動(dòng)釋放,因此如果再在EXE中使用這個(gè)對(duì)象,就會(huì)引發(fā)異常。
 
總的說(shuō),問(wèn)題是由于“聰明”的Delphi編譯器的內(nèi)存管理機(jī)制,和Windows的DLL加/卸載機(jī)制,導(dǎo)致了DLL和EXE中的內(nèi)存存取沖突。
 
解決方法:(只要遵循以下幾個(gè)原則就可以避免大多數(shù)的問(wèn)題)
1.在DLL和EXE之間,盡量不要使用Delphi的自動(dòng)內(nèi)存管理機(jī)制,由程序員自己對(duì)對(duì)象的生命期負(fù)責(zé),比如:
對(duì)于上面的x := TClass.Create(Application);把它改成:
x := TClass.Create(nil);
這樣,Application就不會(huì)再Free它了。當(dāng)然,程序員必須自己來(lái)釋放它。
2.盡量避免在DLL和EXE之間存在不同的指針指向的同一個(gè)對(duì)象。比如,在DLL中有x指向TClass對(duì)象,在EXE中又有y指向TClass對(duì)象,這樣在任何一邊的內(nèi)存釋放都會(huì)導(dǎo)致另一邊的內(nèi)存無(wú)效。
3.其他…
                                                                                                             
Q: 一個(gè)做周期性任務(wù)的線(xiàn)程,在其中需要暫停片刻,然后繼續(xù)運(yùn)行,但如果這時(shí)需要讓線(xiàn)程停止(比如進(jìn)程已經(jīng)結(jié)束了),那該怎么辦?
A:
解決方法一:
在線(xiàn)程中通過(guò)Sleep進(jìn)行周期循環(huán)。(如果在線(xiàn)程中通過(guò)Sleep暫停了,通過(guò)Resume等方法是無(wú)法使得線(xiàn)程重新復(fù)活的)
通過(guò)KillThread來(lái)結(jié)束線(xiàn)程。
這是最簡(jiǎn)單的方法,但也太粗暴,可能會(huì)導(dǎo)致問(wèn)題(KillThread是Windows不推薦使用的API)
 
解決方法二:
在線(xiàn)程中Suspend,在線(xiàn)程外面通過(guò)一個(gè)定時(shí)器,每隔一段時(shí)間就Resume。代碼如下:
// Thread
PRocedure Execute;
begin
while not Terminated do
begin
…   // 處理代碼
Suspend;
end;
end;
 
// 外面
// 定時(shí)器
procedure OnTimer(Sender: Tobject);
begin
thd.Resume;
end;
// 要結(jié)束線(xiàn)程的地方
thd.Resume;
thd.Terminate;
thd.WaitFor;                 // 一般在結(jié)束線(xiàn)程后得通過(guò)WaitFor確認(rèn)線(xiàn)程已經(jīng)真的結(jié)束了。
 
問(wèn)題:線(xiàn)程和外部的耦合太強(qiáng)了,甚至線(xiàn)程的操作周期得通過(guò)外面的定時(shí)器來(lái)確定。
 
解決方法三(這是我想到的最好方法):
在線(xiàn)程中通過(guò)信號(hào)量進(jìn)行暫停操作。
// 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;
 
對(duì)于需要中斷線(xiàn)程的程序,只需如下代碼即可:
begin
  …
 thd.Terminate;
 thd.SetEvent;
thd.WaitFor;
end;

上一篇:Delphi7的IDE概述(二)

下一篇:古都Delphi

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
學(xué)習(xí)交流
熱門(mén)圖片

新聞熱點(diǎn)

疑難解答

圖片精選

網(wǎng)友關(guān)注

主站蜘蛛池模板: 榆林市| 盐源县| 浦江县| 新昌县| 汕头市| 兴国县| 垦利县| 金门县| 毕节市| 邯郸市| 峨山| 漳平市| 璧山县| 宕昌县| 新晃| 色达县| 金川县| 满洲里市| 湘潭县| 咸宁市| 巴彦县| 富平县| 汝州市| 伊通| 喜德县| 商南县| 阿尔山市| 祥云县| 西平县| 南充市| 离岛区| 克拉玛依市| 阳春市| 贵阳市| 黔江区| 肥东县| 姚安县| 贵南县| 城市| 屏南县| 老河口市|