上面所給出的第一種解決方案:
線程(Execute)在執行定時循環;然后先讓 DestroyAThread設置 Terminated屬性,通知線程去結束執行、釋放資源;然后在線程結束執行、釋放資源之后再去通知DestroyAThread,再由DestroyAThread來顯式調用線程的 Free方法來釋放線程
所以結合 FreeOnTerminate的作用,復習一下:
類 Create 了就要 Free;
但 TThread(的子類) 有特殊性, 很多時候我們不能確定新建的線程什么時候執行完(也就是什么時候該釋放);
如果線程執行完畢自己知道釋放就好了, 所以 TThread 給了一個布爾屬性 FreeOnTerminate, 如果為 True, 線程執行完畢后就會自釋放.
進行改造:
首先在線程的Execute方法里面將 FreeOnTerminate設置為True,然后進行自己的定時循環執行;然后DestroyAThread設置Terminated屬性,通知線程去結束執行、釋放資源;然后在線程結束執行、釋放資源之后,因為FreeOnTerminate設置為True了,所以就不要再通知 DestroyAThread,自己在釋放完資源、結束執行之后,就會自釋放。
同樣DestroyAThread設置Terminated屬性之后,就可以直接退出,因為不需要在DestroyAThread里面顯式釋放線程。
同樣也就不需要線程再有 CanFree這種通知別人來釋放它的屬性了,所以也能簡化線程類的設計(在面向對象的程序設計中一個原則就是:類盡可能小,所以那些能不需要的屬性、方法就不要去定義和使用,把冗余的屬性和方法一定要去掉……)
所以新的代碼可以是這樣的
Execute方法:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
procedure
TDoSomeThingThread
.
Execute;
var
i:
Integer
;
begin
inherited
;
FreeOnTerminate:=
True
;
//CanFree := False; //不再需要 CanFree這樣的屬性了,也就簡化了線程類的設計
try
while
not
Self
.
Terminated
do
begin
........
{
在這里編寫該線程具體所要做的事情的代碼邏輯,
如果這里面還是要循環執行一些任務,
最好能在每次循環的時候也都再去檢查一下Terminated的值
如果是True就結束循環,
就是保證在較短的事件內不斷檢查 Terminated標志,保證能夠及時退出
}
........
Sleep(
5
);
Application
.
ProcessMessages;
end
;
finally
//CanFree := True; //不再需要 CanFree這樣的屬性了,也就簡化了線程類的設計
{在這里將線程申請的資源進行釋放……后續操作}
end
;
end
;
|
DestroyAThread方法:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
procedure
DestroyAThread(testThread: TDoSomeThingThread); stdcall;
var
itime:
Cardinal
;
begin
if
Assigned(testThread)
then
begin
testThread
.
Terminate;
//在這里將testThread的 Terminated屬性設置為True
{
這里就只需要通過Terminate方法將線程的Terminated設置為True,
去通知線程結束就行了,
不需要關心線程的釋放問題,因為線程會自己釋放
}
end
;
//這個方案中就不需要使用Free方法去顯式釋放線程資源了,因為線程自己會在執行結束后自動釋放
end
;
|
http://www.cnblogs.com/xumenger/p/4454115.html
