亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

轉載:TThread類剖析

2019-11-18 18:39:09
字體:
來源:轉載
供稿:網友
TThread類剖析

摘要

本文從分析源代碼的角度介紹Delphi5中的TThread類的封裝和運行機理,介紹了TThread類的優缺點。

關鍵詞:Delphi5,TThread,Windows API

 

目錄

1.概述

2.剖析TThread類

2.1 TThread的優點

2.2 TThread的封裝和運行機理

3.結束語

4.致謝

5.參考文獻

全文

1.概述

根據Windows SDK文檔的說明,在Windows線程中的運行實體是類型為:function ThreadFunc(Parameter: pointer): integer的函數(翻譯成Delphi的格式)。但是我們都知道,在Delphi中線程被封裝成一個TThread類。為什么Delphi要將它封裝成一個類?Delphi是如何封裝的呢?我們怎樣才能充分的利用兩者的優點?這就是本下面要介紹的。

2.剖析TThread類

2.1 TThread的優點

將線程作為類來封裝有著許多優點。首先它能清晰、安全的界限線程相關的局部變量和進程相關的全局變量。類——對象的模型到實體的映射關系保證了聲明在類中的任何變量都是局部的,聲明在類外的任何變量都是全局的。所以在寫新線程的Execute函數只要注意對類外部的變量、方法的訪問就可以了,至于類內部的變量、方法則可以任意使用而不用考慮同步的問題。將線程封裝成類的更重要的好處是寫新線程的時候可以充分利用類的優點。你可以通過繼承來重用父類的功能,這實在是一個激動人心的功能。

2.2 TThread的封裝和運行機理

既然已經知道將線程封裝成類有諸多好處,作為一個稱職的程序員一定會去了解Delphi是如何將線程封裝成類的,有沒有更好的封裝的方法的。

Delphi5中TThread類是這樣聲明的:

{ TThread }

EThread = class(Exception);

TThreadMethod = PRocedure of object;
TThreadPriority = (tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest,
tpTimeCritical);

TThread = class
private
FHandle: THandle;
FThreadID: THandle;
FTerminated: Boolean;
FSuspended: Boolean;
FFreeOnTerminate: Boolean;
FFinished: Boolean;
FReturnValue: Integer;
FOnTerminate: TNotifyEvent;
FMethod: TThreadMethod;
FSynchronizeException: TObject;
procedure CallOnTerminate;
function GetPriority: TThreadPriority;
procedure SetPriority(Value: TThreadPriority);
procedure SetSuspended(Value: Boolean);
protected
procedure DoTerminate; virtual;
procedure Execute; virtual; abstract;
procedure Synchronize(Method: TThreadMethod);
property ReturnValue: Integer read FReturnValue write FReturnValue;
property Terminated: Boolean read FTerminated;
public
constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
procedure Resume;
procedure Suspend;
procedure Terminate;
function WaitFor: LongWord;
property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;
property Handle: THandle read FHandle;
property Priority: TThreadPriority read GetPriority write SetPriority;
property Suspended: Boolean read FSuspended write SetSuspended;
property ThreadID: THandle read FThreadID;
property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
end;


準確地說,TThread對象是一個帶有線程實例的不可見窗體對象(長寬都為0),我把這個窗體叫做線程窗體。這個線程窗體有該TThread類的所有對象共享。TThread在構造的時候線程是否第一次創建,如果是就創建線程窗體,然后增加線程計數,最后才建立線程實例。同理,TThread對象在銷毀的時候,先減少線程計數,然后判斷計數是否為0,如果是就銷毀線程窗體。

為什么要建立一個線程窗體呢?答案就是TThread中的同步函數Synchronize()的需要。線程對象存取其他VCL的屬性時與其他線程的同步機制是通過消息隊列來實現的。當線程函數執行Synchronize()時,他就向線程窗體發送一條CM_EXECPROC消息。因為線程窗體是進程的一個窗體(雖然它不可見),所以發向線程窗體的消息都會進入進程消息隊列,而消息隊列的串行處理的特性保證不會出現訪問沖突。這是一個簡單而有效的解決方案。我不知道有沒有人在控制臺程序中應用多線程,如果有的話,TThread類可能就不太適合了。這種情況下要么直接應用線程函數,要么自己寫一個新的TNewThread類了。

Delphi是在TThread類的外面聲明了一個局部函數ThreadProc。這個函數就是Windows SDK中介紹的線程函數,其聲明如下:

function ThreadProc(Thread: TThread): Integer;
var
FreeThread: Boolean;
begin
try
Thread.Execute;
finally
FreeThread := Thread.FFreeOnTerminate;
Result := Thread.FReturnValue;
Thread.FFinished := True;
Thread.DoTerminate;
if FreeThread then Thread.Free;
EndThread(Result);
end;
end;


Delphi沒有將線程函數作為TThread的一個成員函數,我想把ThreadProc放到TThread的Proctected段中TThread的靈活性可能會更好一點,不過現在的方法也不錯??梢钥吹絋hreadProc以TThread對象作為Parameter參數。這樣可以保證TThread對象進入線程的堆棧中,一個TThread對象不破壞另一個同類型TThread對象的數據。當然,創建線程的線程還是可以訪問新線程中的數據的,Terminate過程就是這樣做的。所以TThread的數據還是可能被其他線程破壞的。所以外部線程要訪問線程的數據要小心處理,Terminate()是一個比較典型的:外部線程只寫,內部線程只讀就能很好的工作,如果兩個線程都又讀又寫就可能導致邏輯混亂。

TThread類在構造線程實例是沒有直接調用CreateThread() API函數,而是使用了一個BeginThread()函數。不知是什么原因,該函數并沒有相應的Delphi Help文檔,只是在“TThreadFunc type”的介紹中一筆帶過??赡苁荁orland認為它的參數在以后還會修改吧。不過該函數和CreateThread() API的參數是一模一樣的。這是一個讓人興奮的地方,因為BeginThread()加入了Windows API沒有的異常處理功能。有意思的是,Delphi在BeginThread()由創建了一個新的線程函數,而把原來的線程函數和參數打包成TThreadRec作為新函數的Parameter。有關Delphi5中BeginThread的定義如下:

type
PThreadRec = ^TThreadRec;
TThreadRec = record
Func: TThreadFunc;
Parameter: Pointer;
end;


function ThreadWrapper(Parameter: Pointer): Integer; stdcall;
asm
CALL _FpuInit
XOR ECX,ECX
PUSH EBP
PUSH offset _ExceptionHandler //新增加的Delphi的異常機制
MOV EDX,FS:[ECX]
PUSH EDX
MOV EAX,Parameter
MOV FS:[ECX],ESP

MOV ECX,[EAX].TThreadRec.Parameter
MOV EDX,[EAX].TThreadRec.Func
PUSH ECX
PUSH EDX
CALL _FreeMem
POP EDX
POP EAX
CALL EDX //調用原來的線程函數

XOR EDX,EDX
POP ECX
MOV FS:[EDX],ECX
POP ECX
POP EBP
end;


function BeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
var ThreadId: LongWord): Integer;
var
P: PThreadRec;
begin
New(P);
P.Func := ThreadFunc;
P.Parameter := Parameter;
IsMultiThread := TRUE;
Result := CreateThread(SecurityAttributes, StackSize, @ThreadWrapper, P,
CreationFlags, ThreadID);
end;


讓人覺得美中不足的地方是TThread類在調用BeginThread時傳遞的SercurityAttributes和StackSize參數分別是nil和0,使BeginThread()在調用CreateThread()時使用了缺省的安全設置和默認堆棧大小。有關這兩個參數代表什么意義請查閱Windows SDK文檔。

3.結束語

由于時間倉促,簡單介紹我認為Delphi的幫助文檔中沒有說明的部分。不知你看后有什么疑惑或是覺得我什么講的不對的地方,請來信告知: zg@hzhistar.com 。請多多指教!

4.致謝

"其實,你這篇文章只適用于Delphi5,Delphi6已經改變了Synchronize的做法,改用事件(Event)和臨界區(CriticalSection)的配合來進行同步多線程對VCL控件的訪問。其它還有些少改動的地方,相信你看源碼就會發現。
另外,(或許你已經知道了)Delphi的文檔也很清楚地說明了,調用BeginThread和EndThread來替代Win32API的CreateThread和ExitThread(其實《Windows 核心編程》也指出了應使用開發環境提供的_beginthreadex等函數,具體原因看書吧),至于Delphi,調用BeginThread的一個非常重要的作用就是將全局變量IsMultiThread設為True,因為Delphi的許多運行機制是當該變量為True時才是線程安全的,例如GetMem和FreeMem函數。"
——摘自 "hgd" <hgd01@263.net>

上述的朋友給了我嚴謹的批評和暖和的鼓舞,我在這里表示衷心的感謝!如果你給我提供了你的想法,我就在這里寫上你的大名。:)

5.參考文獻

1.《Windows核心編程》,機械工業出版社,2000年5月(雖然中文翻譯奇爛)
2.《Microsoft Platform SDK》,microsoft, 2001年8月
3.《Delphi 5.0 幫助文檔》、Delphi 5.0源代碼


上一篇:VCL消息處理機制的內幕

下一篇:Windows消息機制初談

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产97在线|亚洲| 亚洲精品97久久| 久久久久久一区二区三区| 青青草国产精品一区二区| 伊人伊成久久人综合网小说| 成人激情免费在线| 青青久久av北条麻妃海外网| 久久影视电视剧凤归四时歌| 日韩中文第一页| 亚洲黄色www网站| 日韩在线激情视频| 日韩av片免费在线观看| 欧美日本精品在线| 国产欧美 在线欧美| 久久久久久久国产| 国产精品久久久久久中文字| 欧美亚洲一级片| 成年人精品视频| 久久精品人人做人人爽| 国产国语刺激对白av不卡| 久久久国产成人精品| 国产精品美女av| 欧美乱大交xxxxx| 亚洲精品91美女久久久久久久| 久久福利视频网| 日韩有码在线播放| 久久久久久久激情视频| 久久精品成人欧美大片古装| 国产免费一区二区三区在线能观看| 国产日韩在线亚洲字幕中文| 亚洲欧美日韩天堂一区二区| 日韩电影第一页| 亚洲欧美三级伦理| 久久全球大尺度高清视频| 精品国产美女在线| 亚洲一区二区三区视频播放| 日韩成人在线网站| 国产一区二区精品丝袜| 97国产一区二区精品久久呦| 亚洲男人第一av网站| 91禁国产网站| 成人欧美一区二区三区黑人孕妇| 精品亚洲一区二区三区在线播放| 亚洲第一精品久久忘忧草社区| 国产精品久久二区| 国产精品国产福利国产秒拍| 欧美日韩精品在线观看| 亚洲天堂男人天堂| 2019中文字幕全在线观看| 91欧美精品成人综合在线观看| 日韩精品在线观看一区| 亚洲欧洲日产国码av系列天堂| 亚洲综合色av| 成人xxxx视频| 亚洲天堂av综合网| 一区二区在线免费视频| 亚洲最大福利视频网| 国产精品专区第二| 日韩欧美国产黄色| 成人福利视频网| 国产亚洲福利一区| 欧美成人合集magnet| 精品久久久久人成| 懂色aⅴ精品一区二区三区蜜月| 茄子视频成人在线| 亚洲成人网在线观看| 日韩视频在线观看免费| 日本a级片电影一区二区| 欧美电影在线观看| 国产精品草莓在线免费观看| 亚洲性猛交xxxxwww| 一区二区欧美在线| 日韩一区二区久久久| 高清视频欧美一级| 欧美精品在线免费| 97国产成人精品视频| 亚洲美女久久久| 亚洲欧洲av一区二区| www.国产一区| 庆余年2免费日韩剧观看大牛| 国产日韩欧美自拍| 日韩美女写真福利在线观看| 亚洲天堂网站在线观看视频| 国产精品久久网| 欧美在线观看视频| 亚洲色图第三页| 亚洲影视九九影院在线观看| 日韩激情av在线免费观看| 亚洲视频专区在线| 欧美日韩一区二区三区在线免费观看| 亚洲国产日韩欧美在线99| 久久久久久久久久久人体| 亚洲成人精品久久久| 2021久久精品国产99国产精品| 亚洲精品美女在线观看播放| 亚洲综合中文字幕在线观看| 日韩电影免费在线观看| 国产一区红桃视频| 97视频在线观看免费| 久久亚洲精品国产亚洲老地址| 亚洲色图15p| 国产精品h片在线播放| 日韩免费观看在线观看| 日本aⅴ大伊香蕉精品视频| 亚洲欧美日韩在线高清直播| 免费99精品国产自在在线| 亚洲性夜色噜噜噜7777| 啊v视频在线一区二区三区| 国产精品嫩草视频| 国产经典一区二区| 欧美日韩国产精品专区| 欧美怡红院视频一区二区三区| 亚洲国产精品va在线看黑人| 国产精品视频一区二区高潮| 777午夜精品福利在线观看| 欧美日韩精品在线观看| 亚洲第一中文字幕在线观看| 欧美激情久久久久久| 日韩av电影在线播放| 久久久久五月天| 国内精品久久久久久| 亚洲人精品午夜在线观看| 国产精品精品久久久| 91久久久国产精品| 国产精品私拍pans大尺度在线| 国产精品视频久久久| 日本精品视频在线播放| 成人激情电影一区二区| 中文字幕欧美精品日韩中文字幕| 欧美激情第1页| 久久久久久久999精品视频| 国产精品久久久久福利| 国产成人精品久久二区二区| 亚洲一区二区三区在线视频| 国产精品久久网| 国产精品第一页在线| 国产精品人成电影| 欧美人成在线视频| 亚洲自拍欧美色图| 国产精品91久久| 在线观看日韩专区| 中文字幕日韩欧美在线视频| 欧美怡春院一区二区三区| 欧美日韩久久久久| 亚洲**2019国产| 国产精品偷伦免费视频观看的| 欧美国产日韩中文字幕在线| 欧美高跟鞋交xxxxhd| 热re99久久精品国产66热| 亚洲欧美制服综合另类| 亚洲激情第一页| www.日韩视频| 一本色道久久综合狠狠躁篇的优点| 亚洲精品国产拍免费91在线| 91精品国产高清久久久久久| 日韩av在线直播| 国产精品美女在线观看| 亚洲欧美日韩另类| 欧美一级大胆视频| 亚洲高清久久久久久| 日韩在线观看电影| 国产精品亚洲精品| 日本成人精品在线| 精品国产电影一区|