?? mfc
字號(hào):
to
DLL),DllMain給它分配動(dòng)態(tài)內(nèi)存并且使用TlsSetValue把線程私有的數(shù)據(jù)按索引保存。DLL函數(shù)可以使用TlsGetValue按索引讀取調(diào)用線程的私有數(shù)據(jù)。</P>
<P align=justify>TLS函數(shù)如下:</P>
<UL>
<P align=justify>
<LI>DWORD TlsAlloc()
<P></P></LI></UL>
<P align=justify>在進(jìn)程或DLL初始化時(shí)調(diào)用,并且把返回值(索引值)作為全局變量保存。</P>
<UL>
<P align=justify>
<LI>BOOL TlsSetValue(
<P></P></LI></UL>
<DIR>
<P align=justify>DWORD dwTlsIndex, //TLS index to set value for </P>
<P align=justify>LPVOID lpTlsValue //value to be stored </P></DIR>
<P align=justify>);</P>
<P align=justify>其中:</P>
<P align=justify>dwTlsIndex是TlsAlloc分配的索引。</P>
<P align=justify>lpTlsValue是線程在TLS槽中存放的數(shù)據(jù)指針,指針指向線程要保存的數(shù)據(jù)。</P>
<P align=justify>線程首先分配動(dòng)態(tài)內(nèi)存并保存數(shù)據(jù)到此內(nèi)存中,然后調(diào)用TlsSetValue保存內(nèi)存指針到TLS槽。</P>
<UL>
<P align=justify>
<LI>LPVOID TlsGetValue(
<P></P></LI></UL>
<P align=justify>DWORD dwTlsIndex // TLS index to retrieve value for</P>
<P align=justify>);</P>
<P align=justify>其中:</P>
<P align=justify>dwTlsIndex是TlsAlloc分配的索引。</P>
<P align=justify>當(dāng)要存取保存的數(shù)據(jù)時(shí),使用索引得到數(shù)據(jù)指針。</P>
<UL>
<P align=justify>
<LI>BOOL TlsFree(
<P></P></LI></UL>
<P align=justify>DWORD dwTlsIndex // TLS index to free</P>
<P align=justify>);</P>
<P align=justify>其中:</P>
<P align=justify>dwTlsIndex是TlsAlloc分配的索引。</P>
<P align=justify>當(dāng)每一個(gè)線程都不再使用局部存儲(chǔ)數(shù)據(jù)時(shí),線程釋放它分配的動(dòng)態(tài)內(nèi)存。在TLS索引不再需要時(shí),使用TlsFree釋放索引。</P>
<OL>
<OL>
<P align=justify>
<LI><A name=_Toc445889085></A><A name=_Toc445782488></A><A
name=_Toc452640949></A><A name=_Toc457299047></A><B>線程同步</B>
<P></P>
<P
align=justify>同步可以保證在一個(gè)時(shí)間內(nèi)只有一個(gè)線程對(duì)某個(gè)資源(如操作系統(tǒng)資源等共享資源)有控制權(quán)。共享資源包括全局變量、公共數(shù)據(jù)成員或者句柄等。同步還可以使得有關(guān)聯(lián)交互作用的代碼按一定的順序執(zhí)行。</P>
<P align=justify>Win32提供了一組對(duì)象用來(lái)實(shí)現(xiàn)多線程的同步。</P>
<P align=justify>這些對(duì)象有兩種狀態(tài):獲得信號(hào)(Signaled)或者沒(méi)有或則信號(hào)(Not signaled)。線程通過(guò)Win32
API提供的同步等待函數(shù)(Wait
functions)來(lái)使用同步對(duì)象。一個(gè)同步對(duì)象在同步等待函數(shù)調(diào)用時(shí)被指定,調(diào)用同步函數(shù)地線程被阻塞(blocked),直到同步對(duì)象獲得信號(hào)。被阻塞的線程不占用CPU時(shí)間。</P>
<OL>
<P align=justify>
<LI><A name=_Toc445889086></A><A name=_Toc445782489></A><A
name=_Toc452640950></A><A name=_Toc457299048></A><B>同步對(duì)象</B>
<P></P></LI></OL></LI></OL></OL>
<P
align=justify>同步對(duì)象有:Critical_section(關(guān)鍵段),Event(事件),Mutex(互斥對(duì)象),Semaphores(信號(hào)量)。</P>
<P align=justify>下面,解釋怎么使用這些同步對(duì)象。</P>
<OL>
<P align=justify>
<LI>關(guān)鍵段對(duì)象:
<P></P>
<P align=justify>首先,定義一個(gè)關(guān)鍵段對(duì)象cs:</P>
<P align=justify>CRITICAL_SECTION cs;</P>
<P align=justify>然后,初始化該對(duì)象。初始化時(shí)把對(duì)象設(shè)置為NOT_SINGALED,表示允許線程使用資源:</P>
<P align=justify>InitializeCriticalSection(&cs);</P>
<P
align=justify>如果一段程序代碼需要對(duì)某個(gè)資源進(jìn)行同步保護(hù),則這是一段關(guān)鍵段代碼。在進(jìn)入該關(guān)鍵段代碼前調(diào)用EnterCriticalSection函數(shù),這樣,其他線程都不能執(zhí)行該段代碼,若它們?cè)噲D執(zhí)行就會(huì)被阻塞。</P>
<P
align=justify>完成關(guān)鍵段的執(zhí)行之后,調(diào)用LeaveCriticalSection函數(shù),其他的線程就可以繼續(xù)執(zhí)行該段代碼。如果該函數(shù)不被調(diào)用,則其他線程將無(wú)限期的等待。</P>
<P align=justify></P>
<LI>事件對(duì)象
<P></P>
<P
align=justify>首先,調(diào)用CreateEvent函數(shù)創(chuàng)建一個(gè)事件對(duì)象,該函數(shù)返回一個(gè)事件句柄。然后,可以設(shè)置(SetEvent)或者復(fù)位(ResetEvent)一個(gè)事件對(duì)象,也可以發(fā)一個(gè)事件脈沖(PlusEvent),即設(shè)置一個(gè)事件對(duì)象,然后復(fù)位它。復(fù)位有兩種形式:自動(dòng)復(fù)位和人工復(fù)位。在創(chuàng)建事件對(duì)象時(shí)指定復(fù)位形式。。</P>
<P
align=justify>自動(dòng)復(fù)位:當(dāng)對(duì)象獲得信號(hào)后,就釋放下一個(gè)可用線程(優(yōu)先級(jí)別最高的線程;如果優(yōu)先級(jí)別相同,則等待隊(duì)列中的第一個(gè)線程被釋放)。</P>
<P align=justify>人工復(fù)位:當(dāng)對(duì)象獲得信號(hào)后,就釋放所有可利用線程。</P>
<P align=justify>最后,使用CloseHandle銷(xiāo)毀創(chuàng)建的事件對(duì)象。</P>
<P align=justify></P>
<LI>互斥對(duì)象
<P></P>
<P
align=justify>首先,調(diào)用CreateMutex創(chuàng)建互斥對(duì)象;然后,調(diào)用等待函數(shù),可以的話利用關(guān)鍵資源;最后,調(diào)用RealseMutex釋放互斥對(duì)象。</P>
<P align=justify>互斥對(duì)象可以在進(jìn)程間使用,但關(guān)鍵段對(duì)象只能用于同一進(jìn)程的線程之間。</P>
<P align=justify></P>
<LI>信號(hào)量對(duì)象
<P></P>
<P align=justify>在Win32中,信號(hào)量的數(shù)值變?yōu)?時(shí)給以信號(hào)。在有多個(gè)資源需要管理時(shí)可以使用信號(hào)量對(duì)象。</P>
<P
align=justify>首先,調(diào)用CreateSemaphore創(chuàng)建一個(gè)信號(hào)量;然后,調(diào)用等待函數(shù),如果允許的話,則利用關(guān)鍵資源;最后,調(diào)用RealeaseSemaphore釋放信號(hào)量對(duì)象。</P>
<P align=justify></P>
<LI>此外,還有其他句柄可以用來(lái)同步線程:
<P></P></LI></OL>
<P align=justify>文件句柄(FILE HANDLES)</P>
<P align=justify>命名管道句柄(NAMED PIPE HANDELS)</P>
<P align=justify>控制臺(tái)輸入緩沖區(qū)句柄(CONSOLE INPUT BUFFER HANDLES)</P>
<P align=justify>通訊設(shè)備句柄(COMMUNICTION DEVICE HANDLES)</P>
<P align=justify>進(jìn)程句柄(PROCESS HANDLES)</P>
<P align=justify>線程句柄(THREAD HANDLES)</P>
<P align=justify>例如,當(dāng)一個(gè)進(jìn)程或線程結(jié)束時(shí),進(jìn)程或線程句柄獲得信號(hào),等待該進(jìn)程或者線程結(jié)束的線程被釋放。</P>
<OL>
<OL>
<OL>
<P align=justify>
<LI><A name=_Toc445889087></A><A name=_Toc445782490></A><A
name=_Toc452640951></A><A name=_Toc457299049></A><B>等待函數(shù)</B>
<P></P></LI></OL></OL></OL>
<P align=justify>Win32提供了一組等待函數(shù)用來(lái)讓一個(gè)線程阻塞自己的執(zhí)行。等待函數(shù)分三類(lèi):</P>
<OL>
<P align=justify>
<LI>等待單個(gè)對(duì)象的(FOR SINGLE OBJECT):
<P></P>
<P align=justify>這類(lèi)函數(shù)包括:</P>
<P align=justify>SignalObjectAndWait</P>
<P align=justify>WaitForSingleObject</P>
<P align=justify>WaitForSingleObjectEx</P>
<P align=justify>函數(shù)參數(shù)包括同步對(duì)象的句柄和等待時(shí)間等。</P>
<P align=justify>在以下情況下等待函數(shù)返回:</P>
<P align=justify>同步對(duì)象獲得信號(hào)時(shí)返回;</P>
<P
align=justify>等待時(shí)間達(dá)到了返回:如果等待時(shí)間不限制(Infinite),則只有同步對(duì)象獲得信號(hào)才返回;如果等待時(shí)間為0,則在測(cè)試了同步對(duì)象的狀態(tài)之后馬上返回。</P>
<P align=justify></P>
<LI>等待多個(gè)對(duì)象的(FOR MULTIPLE OBJECTS)
<P></P>
<P align=justify>這類(lèi)函數(shù)包括:</P>
<P align=justify>WaitForMultipleObjects</P>
<P align=justify>WaitForMultipleObjectsEx</P>
<P align=justify>MsgWaitForMultipleObjects</P>
<P align=justify>MsgWaitForMultipleObjectsEx</P>
<P align=justify>函數(shù)參數(shù)包括同步對(duì)象的句柄,等待時(shí)間,是等待一個(gè)還是多個(gè)同步對(duì)象等等。</P>
<P align=justify>在以下情況下等待函數(shù)返回:</P>
<P align=justify>一個(gè)或全部同步對(duì)象獲得信號(hào)時(shí)返回(在參數(shù)中指定是等待一個(gè)或多個(gè)同步對(duì)象);</P>
<P
align=justify>等待時(shí)間達(dá)到了返回:如果等待時(shí)間不限制(Infinite),則只有同步對(duì)象獲得信號(hào)才返回;如果等待時(shí)間為0,則在測(cè)試了同步對(duì)象的狀態(tài)之后馬上返回。</P>
<P align=justify></P>
<LI>可以發(fā)出提示的函數(shù)(ALTERABLE)
<P></P></LI></OL>
<P align=justify>這類(lèi)函數(shù)包括:</P>
<P align=justify>MsgWaitForMultipleObjectsEx</P>
<P align=justify>SignalObjectAndWait</P>
<P align=justify>WaitForMultipleObjectsEx</P>
<P align=justify>WaitForSingleObjectEx</P>
<P align=justify>這些函數(shù)主要用于重疊(Overlapped)的I/O(異步I/O)。</P>
<OL>
<OL>
<P align=justify>
<LI><A name=_Toc445889088></A><A name=_Toc445782491></A><A
name=_Toc452640952></A><A name=_Toc457299050></A><B>MFC的線程處理</B>
<P></P>
<P align=justify>在Win32
API的基礎(chǔ)之上,MFC提供了處理線程的類(lèi)和函數(shù)。處理線程的類(lèi)是CWinThread,函數(shù)是AfxBeginThread、AfxEndThread等。</P>
<P align=justify>表5-6解釋了CWinThread的成員變量和函數(shù)。</P>
<P
align=justify>CWinThread是MFC線程類(lèi),它的成員變量m_hThread和m_hThreadID是對(duì)應(yīng)的Win32線程句柄和線程ID。</P>
<P align=justify>MFC明確區(qū)分兩種線程:用戶(hù)界面線程(User interface thread)和工作者線程(Worker
thread)。用戶(hù)界面線程一般用于處理用戶(hù)輸入并對(duì)用戶(hù)產(chǎn)生的事件和消息作出應(yīng)答。工作者線程用于完成不要求用戶(hù)輸入的任務(wù),如耗時(shí)計(jì)算。</P>
<P align=justify>Win32
API并不區(qū)分線程類(lèi)型,它只需要知道線程的開(kāi)始地址以便它開(kāi)始執(zhí)行線程。MFC為用戶(hù)界面線程特別地提供消息泵來(lái)處理用戶(hù)界面的事件。CWinApp對(duì)象是用戶(hù)界面線程對(duì)象的一個(gè)例子,CWinApp從類(lèi)CWinThread派生并處理用戶(hù)產(chǎn)生的事件和消息。</P>
<OL>
<P align=justify>
<LI><A name=_Toc445889089></A><A name=_Toc445782492></A><A
name=_Toc452640953></A><A name=_Toc457299051></A><B>創(chuàng)建用戶(hù)界面線程</B>
<P></P></LI></OL></LI></OL></OL>
<P align=justify>通過(guò)以下步驟創(chuàng)建一個(gè)用戶(hù)界面線程:</P>
<UL>
<P align=justify>
<LI>從CWinThread派生一個(gè)有動(dòng)態(tài)創(chuàng)建能力的類(lèi)。使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏來(lái)支持動(dòng)態(tài)創(chuàng)建。
<P></P>
<P align=justify></P>
<LI>覆蓋CWinThread的一些虛擬函數(shù),可以覆蓋的函數(shù)見(jiàn)表5-4關(guān)于CWinThread的部分。其中,函數(shù)InitInstance是必須覆蓋的,ExitInstance通常是要覆蓋的。
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -