當(dāng)前位置:首頁(yè) > 芯聞號(hào) > 充電吧
[導(dǎo)讀]l??????? 窗口置頂::SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | WS_EX_TOPMOST);l?

l??????? 窗口置頂

::SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | WS_EX_TOPMOST);

l??????? 取消置頂

::SetWindowPos(GetSafeHwnd(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

?

l??????? 寫(xiě)入配置文件。

::WritePrivateProfileString("Settings","AlwaysOnTop",m_bAlwaysOnTop? "1":"0",".\Settings.ini");


l??????? 讀取配置文件

::GetPrivateProfileInt("Selections","m_bAddNew",0,".\Settings.ini")

?

l??????? 數(shù)據(jù)綁定

DDX_Check(pDX, IDC_CHECK1_ADDNEW, m_bAddNew);

?

//讀寫(xiě)INI/ini文件*************************************************?

//寫(xiě)入值字段名變量名值帶目錄文件名?
WritePrivateProfileString("目錄","path",cs, regpath);?
//寫(xiě)入結(jié)構(gòu)體字段名變量名值大小帶目錄文件名?
WritePrivateProfileStruct("字體","font",&LF,sizeof(LOGFONT),regpath);//結(jié)構(gòu)體?
//讀入字符字段名變量名默認(rèn)值字符緩沖區(qū)長(zhǎng)度帶目錄文件名?
GetPrivateProfileString("目錄","path","", buffer.GetBuffer(260),260,regpath);?
//讀入整數(shù)值字段名變量名默認(rèn)值帶目錄文件名?
GetPrivateProfileInt("colors","red",255, regpath);?
//讀入結(jié)構(gòu)體字段名變量名值大小帶目錄文件名?
GetPrivateProfileStruct("字體","font",&LF,sizeof(LOGFONT),regpath);?

線程

進(jìn)程是資源分配的基本單位。所有與該進(jìn)程有關(guān)的資源,都被記錄在進(jìn)程控制塊PCB中。以表示該進(jìn)程擁有這些資源或正在使用它們?! ?/p>

另外,進(jìn)程也是搶占處理機(jī)的調(diào)度單位,它擁有一個(gè)完整的虛擬地址空間。   

與進(jìn)程相對(duì)應(yīng),線程與資源分配無(wú)關(guān),它屬于某一個(gè)進(jìn)程,并與進(jìn)程內(nèi)的其他線程一起共享進(jìn)程的資源?! ?/p>

當(dāng)進(jìn)程發(fā)生調(diào)度時(shí),不同的進(jìn)程擁有不同的虛擬地址空間,而同一進(jìn)程內(nèi)的不同線程共享同一地址空間。   

線程只由相關(guān)堆棧(系統(tǒng)棧或用戶(hù)棧)寄存器和線程控制表TCB組成。寄存器可被用來(lái)存儲(chǔ)線程內(nèi)的局部變量,但不能存儲(chǔ)其他線程的相關(guān)變量。  

發(fā)生進(jìn)程切換與發(fā)生線程切換時(shí)相比較,進(jìn)程切換時(shí)涉及到有關(guān)資源指針的保存以及地址空間的變化等問(wèn)題;線程切換時(shí),由于同進(jìn)程內(nèi)的線程共享資源和地址空間,將不涉及資源信息的保存和地址變化問(wèn)題,從而減少了操作系統(tǒng)的開(kāi)銷(xiāo)時(shí)間。而且,進(jìn)程的調(diào)度與切換都是由操作系統(tǒng)內(nèi)核完成,而線程則既可由操作系統(tǒng)內(nèi) 核完成,也可由用戶(hù)程序進(jìn)行。

因?yàn)檫M(jìn)程內(nèi)的線程分享相同的資源,所以需要在系統(tǒng)級(jí)別上設(shè)置控制機(jī)制來(lái)保證數(shù)據(jù)的完整性。當(dāng)一個(gè)線程修改了某個(gè)變量,而另一個(gè)線程試圖讀取它時(shí),或者兩個(gè)線程同時(shí)修改同一變量,就會(huì)影響到數(shù)據(jù)的完整性,為防止這個(gè)問(wèn)題,操作系統(tǒng)提供了一種相互排斥對(duì)象,簡(jiǎn)寫(xiě)為mutex。在多線程程序中,mutex是通過(guò)編程來(lái)實(shí)現(xiàn)的,可防止多個(gè)線程在同一時(shí)間訪問(wèn)同一資源。??? 當(dāng)一個(gè)線程需要訪問(wèn)某一資源時(shí),它必須先請(qǐng)求一個(gè)mutex,一旦線程得到一個(gè)mutex,其他想獲取同一mutex的線程被阻塞,并處于低CPU占用的等待狀態(tài);一旦這個(gè)線程完成了數(shù)據(jù)訪問(wèn),它會(huì)釋放對(duì)應(yīng)的mutex,這就允許其他線程獲取以訪問(wèn)相關(guān)的數(shù)據(jù)。

線程,有時(shí)被稱(chēng)為輕量級(jí)進(jìn)程(Lightweight Process,LWP),是程序執(zhí)行流的最小單元。一個(gè)標(biāo)準(zhǔn)的線程由線程ID,當(dāng)前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進(jìn)程中的一個(gè)實(shí)體,是被系統(tǒng)獨(dú)立調(diào)度和分派的基本單位,線程自己不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源,但它可與同屬一個(gè)進(jìn)程的其它線程共享進(jìn)程所擁有的全部資源。一個(gè)線程可以創(chuàng)建和撤消另一個(gè)線程,同一進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行。由于線程之間的相互制約,致使線程在運(yùn)行中呈現(xiàn)出間斷性。線程也有就緒、阻塞和運(yùn)行三種基本狀態(tài)。每一個(gè)程序都至少有一個(gè)線程,若程序只有一個(gè)線程,那就是程序本身。

線程是程序中一個(gè)單一的順序控制流程。在單個(gè)程序中同時(shí)運(yùn)行多個(gè)線程完成不同的工作,稱(chēng)為多線程。???

每個(gè)線程中都應(yīng)具有一個(gè)用于控制線程運(yùn)行的線程控制塊TCB,用于指示被執(zhí)行指令序列的程序計(jì)數(shù)器、保留局部變量、少數(shù)狀態(tài)參數(shù)和返回地址等的一組寄存器和堆棧。

1.輕型實(shí)體   

線程中的實(shí)體基本上不擁有系統(tǒng)資源,只是有一點(diǎn)必不可少的、能保證獨(dú)立運(yùn)行的資源,比如,在每個(gè)線程中都應(yīng)具有一個(gè)用于控制線程運(yùn)行的線程控制塊TCB,用于指示被執(zhí)行指令序列的程序計(jì)數(shù)器、保留局部變量、少數(shù)狀態(tài)參數(shù)和返回地址等的一組寄存器和堆棧。   

2.獨(dú)立調(diào)度和分派的基本單位。   

在多線程O(píng)S中,線程是能獨(dú)立運(yùn)行的基本單位,因而也是獨(dú)立調(diào)度和分派的基本單位。由于線程很“輕”,故線程的切換非常迅速且開(kāi)銷(xiāo)小。   

3.可并發(fā)執(zhí)行。   

在一個(gè)進(jìn)程中的多個(gè)線程之間,可以并發(fā)執(zhí)行,甚至允許在一個(gè)進(jìn)程中所有線程都能并發(fā)執(zhí)行;同樣,不同進(jìn)程中的線程也能并發(fā)執(zhí)行。  

4.共享進(jìn)程資源。   

在同一進(jìn)程中的各個(gè)線程,都可以共享該進(jìn)程所擁有的資源,這首先表現(xiàn)在:所有線程都具有相同的地址空間(進(jìn)程的地址空間),這意味著,線程可以訪問(wèn)該地址空間的每一個(gè)虛地址;此外,還可以訪問(wèn)進(jìn)程所擁有的已打開(kāi)文件、定時(shí)器、信號(hào)量機(jī)構(gòu)等。

  

線程與進(jìn)程的區(qū)別可以歸納為以下幾點(diǎn):   

l???????? 地址空間和其它資源(如打開(kāi)文件):進(jìn)程間相互獨(dú)立,同一進(jìn)程的各線程間共享。某進(jìn)程內(nèi)的線程在其它進(jìn)程不可見(jiàn)。  

l???????? 通信:進(jìn)程間通信IPC,線程間可以直接讀寫(xiě)進(jìn)程數(shù)據(jù)段(如全局變量)來(lái)進(jìn)行通信——需要進(jìn)程同步和互斥手段的輔助,以保證數(shù)據(jù)的一致性。   

l???????? 調(diào)度和切換:線程上下文切換比進(jìn)程上下文切換要快得多?! ?/p>

l???????? 在多線程O(píng)S中,進(jìn)程不是一個(gè)可執(zhí)行的實(shí)體。

?

線程的生命狀態(tài)與周期

1.新建 2.就緒 3.運(yùn)行 4.阻塞 5.死亡

線程有兩個(gè)基本類(lèi)型:

  用戶(hù)級(jí)線程:管理過(guò)程全部由用戶(hù)程序完成,操作系統(tǒng)內(nèi)核心只對(duì)進(jìn)程進(jìn)行管理。

系統(tǒng)級(jí)線程(核心級(jí)線程):由操作系統(tǒng)內(nèi)核進(jìn)行管理。操作系統(tǒng)內(nèi)核給應(yīng)用程序提供相應(yīng)的系統(tǒng)調(diào)用和應(yīng)用程序接口API,以使用戶(hù)程序可以創(chuàng)建、執(zhí)行、撤消線程。

?

?

函數(shù)

操作系統(tǒng)

描述

使用的類(lèi)

CreateThread

Windows

創(chuàng)建一個(gè)Windows線程

CThread

WaitForSingleObject

Windows

等待一個(gè)對(duì)象有信號(hào)

CThread, CMutex, CEvent

CreateMutex

Windows

創(chuàng)建一個(gè)命名或未命名的mutex

CMutex

CloseHandle

Windows

關(guān)閉某一Windows句柄以釋放資源

CMutex, CEvent, CThread

ReleaseMutex

Windows

釋放某一之前獲取,并由WaitForSingleObject鎖定的mutex

CMutex CEvent

CreateEvent

Windows

創(chuàng)建一個(gè)Windows事件對(duì)象

CEvent

SetEvent

Windows

設(shè)置某一Windows事件對(duì)象為有信號(hào)狀態(tài)

CEvent

?

?

CMutex類(lèi)的函數(shù)

函數(shù)

描述

void CMutex()

構(gòu)造函數(shù)

void Lock()

鎖定mutex對(duì)象或當(dāng)它阻塞時(shí)等待

void Unlock()

解鎖之前阻塞的mutex

?

2、DWORD SuspendThread(HANDLE hThread);

該函數(shù)用于掛起指定的線程,如果函數(shù)執(zhí)行成功,則線程的執(zhí)行被終止。 3、DWORD

3、ResumeThread(HANDLE hThread);

該函數(shù)用于結(jié)束線程的掛起狀態(tài),執(zhí)行線程。

4、VOID ExitThread(DWORD dwExitCode);

該函數(shù)用于線程終結(jié)自身的執(zhí)行,主要在線程的執(zhí)行函數(shù)中被調(diào)用。其中參數(shù)dwExitCode用來(lái)設(shè)置線程的退出碼。

5、BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);

  一般情況下,線程運(yùn)行結(jié)束之后,線程函數(shù)正常返回,但是應(yīng)用程序可以調(diào)用TerminateThread強(qiáng)行終止某一線程的執(zhí)行。各參數(shù)含義如下:

hThread:將被終結(jié)的線程的句柄;

dwExitCode:用于指定線程的退出碼。

  使用TerminateThread()終止某個(gè)線程的執(zhí)行是不安全的,可能會(huì)引起系統(tǒng)不穩(wěn)定;雖然該函數(shù)立即終止線程的執(zhí)行,但并不釋放線程所占用的資源。因此,一般不建議使用該函數(shù)。

6、BOOL PostThreadMessage(DWORD idThread,

??????????? UINT Msg,

??????????? WPARAM wParam,

??????????? LPARAM lParam);

?

l???????? 該函數(shù)將一條消息放入到指定線程的消息隊(duì)列中,并且不等到消息被該線程處理時(shí)便返回。

l???????? idThread:將接收消息的線程的ID;

l???????? Msg:指定用來(lái)發(fā)送的消息;

l???????? wParam:同消息有關(guān)的字參數(shù);

l???????? lParam:同消息有關(guān)的長(zhǎng)參數(shù);

l???????? 調(diào)用該函數(shù)時(shí),如果即將接收消息的線程沒(méi)有創(chuàng)建消息循環(huán),則該函數(shù)執(zhí)行失敗。

volatile修飾符的作用是告訴編譯器無(wú)需對(duì)該變量作任何的優(yōu)化,即無(wú)需將它放到一個(gè)寄存器中,并且該值可被外部改變。對(duì)于多線程引用的全局變量來(lái)說(shuō),volatile 是一個(gè)非常重要的修飾符。

?

終止線程

WaitForSingleObject函數(shù),其函數(shù)原型為:DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);

?

hHandle為要監(jiān)視的對(duì)象(一般為同步對(duì)象,也可以是線程)的句柄;

dwMilliseconds為hHandle對(duì)象所設(shè)置的超時(shí)值,單位為毫秒;

  當(dāng)在某一線程中調(diào)用該函數(shù)時(shí),線程暫時(shí)掛起,系統(tǒng)監(jiān)視hHandle所指向的對(duì)象的狀態(tài)。如果在掛起的dwMilliseconds毫秒內(nèi),線程所等待的對(duì)象變?yōu)橛行盘?hào)狀態(tài),則該函數(shù)立即返回;如果超時(shí)時(shí)間已經(jīng)到達(dá)dwMilliseconds毫秒,但hHandle所指向的對(duì)象還沒(méi)有變成有信號(hào)狀態(tài),函數(shù)照樣返回。參數(shù)dwMilliseconds有兩個(gè)具有特殊意義的值:0和INFINITE。若為0,則該函數(shù)立即返回;若為INFINITE,則線程一直被掛起,直到hHandle所指向的對(duì)象變?yōu)橛行盘?hào)狀態(tài)時(shí)為止。

  本例程調(diào)用該函數(shù)的作用是按下IDC_START按鈕后,一直等到線程返回,再恢復(fù)IDC_START按鈕正常狀態(tài)。編譯運(yùn)行該例程并細(xì)心體會(huì)。

::TerminateThread(m_hThread, 0 );

m_hThread = NULL;

?

HANDLE m_hThread;//線程

DWORD m_hThreadId;? //線程ID

? static DWORD WINAPI ThreadProc( LPVOID lParam ) //線程函數(shù),非類(lèi)成員

{

??? CString str;

??? str.Format(L"%d",AfxGetApp()->m_nThreadID);

//AfxGetApp()獲取當(dāng)前運(yùn)行的程序?qū)ο笾羔楥heheDlg*

??? ((CheheDlg*)lParam)->SetDlgItemText(IDC_EDIT1,str);//轉(zhuǎn)換對(duì)象指針

??? return 1;

}

//如果未傳遞當(dāng)前運(yùn)行的句柄。

??? CListBox *list;

??? list=(CListBox*)AfxGetApp()->GetMainWnd()->GetDlgItem(IDC_LIST1);

??? list->AddString(str);

AfxGetApp()獲取了該應(yīng)用程序的實(shí)例句柄

GetMainWnd()獲取了該應(yīng)用程序的主窗口

?

??? m_hThread=::CreateThread(NULL,0,ThreadProc,this,0,&m_hThreadId);//this當(dāng)前對(duì)象指針

?

線程的創(chuàng)建

使用CreateThread函數(shù)創(chuàng)建線程,CreateThread的原型如下:

HANDLE CreateThread(

LPSECURITY_ATTRIBUTES lpThreadAttributes,

DWORD dwStackSize,

LPTHREAD_START_ROUTINE lpStartAddress,

LPVOID lpParameter,

DWORD dwCreationFlags, // creation flags

LPDWORD lpThreadId

);

其中:

l???????? lpThreadAttributes表示創(chuàng)建線程的安全屬性,NT下有用。

l???????? dwStackSize指定線程棧的尺寸,如果為0則與進(jìn)程主線程棧相同。

l???????? lpStartAddress指定線程開(kāi)始運(yùn)行的地址。

l???????? lpParameter表示傳遞給線程的32位的參數(shù)。

l???????? dwCreateFlages表示是否創(chuàng)建后掛起線程(取值CREATE_SUSPENDED),掛起后調(diào)用ResumeThread繼續(xù)執(zhí)行。

l???????? lpThreadId用來(lái)存放返回的線程ID。

?

??? h=CreateThread(NULL,NULL,ThreadProc,this,CREATE_SUSPENDED,NULL);//創(chuàng)建后掛起線程

ResumeThread(h);//恢復(fù)線程

SuspendThread(h);//掛起線程

?

static DWORD WINAPI ThreadProc( LPVOID lParam )

{

??? CString str;

??? CTime c;

??? while(1)

??? {

??????? c=CTime::GetCurrentTime();

??????? str=c.Format("%H:%M:%S");

??? ((CheheDlg*)lParam)->SetDlgItemText(IDC_EDIT1,str);

??? }

??????? return 0;

}

??

//獲取當(dāng)前線程的優(yōu)先級(jí)

??????? DWORD dw= GetThreadPriority(GetCurrentThread());

??????? str.Format(L"%x",dw);

?

//設(shè)置線程優(yōu)先級(jí):1:線程句柄? 2:優(yōu)先級(jí)THREAD_PRIORITY_NORMAL??? 0

BOOL WINAPI SetThreadPriority(

? __in????????? HANDLE hThread,

? __in????????? int nPriority

);

?

線程的終止

以下情況終止一個(gè)線程:

l???????? 調(diào)用了ExitThread函數(shù);

l???????? 線程函數(shù)返回:主線程返回導(dǎo)致ExitProcess被調(diào)用,其他線程返回導(dǎo)致ExitThread被調(diào)用;

l???????? 調(diào)用ExitProcess導(dǎo)致進(jìn)程的所有線程終止;

l???????? 調(diào)用TerminateThread終止一個(gè)線程;

l???????? 調(diào)用TerminateProcess終止一個(gè)進(jìn)程時(shí),導(dǎo)致其所有線程的終止。

l???????? 當(dāng)用TerminateProcess或者TerminateThread終止進(jìn)程或線程時(shí),DLL的入口函數(shù)DllMain不會(huì)被執(zhí)行(如果有DLL的話)。

?

線程同步

同步可以保證在一個(gè)時(shí)間內(nèi)只有一個(gè)線程對(duì)某個(gè)資源(如操作系統(tǒng)資源等共享資源)有控制權(quán)。共享資源包括全局變量、公共數(shù)據(jù)成員或者句柄等。同步還可以使得有關(guān)聯(lián)交互作用的代碼按一定的順序執(zhí)行。

同步對(duì)象有:Critical_section(關(guān)鍵段),Event(事件),Mutex(互斥對(duì)象),Semaphores(信號(hào)量)。

?

在Win32 API的基礎(chǔ)之上,MFC提供了處理線程的類(lèi)和函數(shù)。處理線程的類(lèi)是CWinThread,函數(shù)是AfxBeginThread、AfxEndThread等。

CWinThread是MFC線程類(lèi),它的成員變量m_hThread和m_hThreadID是對(duì)應(yīng)的Win32線程句柄和線程ID。

MFC明確區(qū)分兩種線程:用戶(hù)界面線程(User interface thread)和工作者線程(Worker thread)。用戶(hù)界面線程一般用于處理用戶(hù)輸入并對(duì)用戶(hù)產(chǎn)生的事件和消息作出應(yīng)答。工作者線程用于完成不要求用戶(hù)輸入的任務(wù),如耗時(shí)計(jì)算。

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)生的事件和消息。

?

 為了防止用戶(hù)定義的消息ID與系統(tǒng)的消息ID沖突,MS(Microsoft)定義了一個(gè)宏WM_USER,小于WM_USER的ID被系統(tǒng)使用,大于WM_USER的ID被用戶(hù)使用。

?

PostMessage是Windows API(應(yīng)用程序接口) 中的一個(gè)常用函數(shù),用于將一條消息放入到消息隊(duì)列中。該函數(shù)將一個(gè)消息放入(寄送)到與指定窗口創(chuàng)建的線程相聯(lián)系消息隊(duì)列里,不等待線程處理消息就返回,是異步消息模式。消息隊(duì)列里的消息通過(guò)調(diào)用GetMessage和PeekMessage取得。函數(shù)原型:B00L PostMessage(HWNDhWnd,UINTMsg,WPARAMwParam,LPARAMlParam);   

參數(shù)說(shuō)明:  

hWnd:其窗口程序接收消息的窗口的句柄??扇∮刑囟êx的兩個(gè)值:   

HWND_BROADCAST:消息被寄送到系統(tǒng)的所有頂層窗口,包括無(wú)效或不可見(jiàn)的非自身?yè)碛写翱凇?被覆蓋的窗口和彈出式窗口。消息不被寄送到子窗口  

NULL:此函數(shù)的操作和調(diào)用參數(shù)dwThread設(shè)置為當(dāng)前線程的標(biāo)識(shí)符PostThreadMessage函數(shù)一樣   

Msg:指定被寄送的消息。   

wParam:指定附加的消息特定的信息。   

IParam:指定附加的消息特定的信息。   

返回值:如果函數(shù)調(diào)用成功,返回非零值:如果函數(shù)調(diào)用失敗,返回值是零。若想獲得更多的錯(cuò)誤信息,請(qǐng)調(diào)用GetLastError函數(shù)。

?

使隸屬于同一進(jìn)程的各線程協(xié)調(diào)一致地工作稱(chēng)為線程同步

?

使用 CCriticalSection 類(lèi)

  當(dāng)多個(gè)線程訪問(wèn)一個(gè)獨(dú)占性共享資源時(shí),可以使用“臨界區(qū)”對(duì)象。任一時(shí)刻只有一個(gè)線程可以擁有臨界區(qū)對(duì)象,擁有臨界區(qū)的線程可以訪問(wèn)被保護(hù)起來(lái)的資源或代碼段,其他希望進(jìn)入臨界區(qū)的線程將被掛起等待,直到擁有臨界區(qū)的線程放棄臨界區(qū)時(shí)為止,這樣就保證了不會(huì)在同一時(shí)刻出現(xiàn)多個(gè)線程訪問(wèn)共享資源。

?

CCriticalSection類(lèi)的用法非常簡(jiǎn)單,步驟如下:

定義CCriticalSection類(lèi)的一個(gè)全局對(duì)象(以使各個(gè)線程均能訪問(wèn)),如CCriticalSection critical_section;

在訪問(wèn)需要保護(hù)的資源或代碼之前,調(diào)用CCriticalSection類(lèi)的成員Lock()獲得臨界區(qū)對(duì)象: critical_section.Lock();

?

在線程中調(diào)用該函數(shù)來(lái)使線程獲得它所請(qǐng)求的臨界區(qū)。如果此時(shí)沒(méi)有其它線程占有臨界區(qū)對(duì)象,則調(diào)用Lock()的線程獲得臨界區(qū);否則,線程將被掛起,并放入到一個(gè)系統(tǒng)隊(duì)列中等待,直到當(dāng)前擁有臨界區(qū)的線程釋放了臨界區(qū)時(shí)為止。

訪問(wèn)臨界區(qū)完畢后,使用CCriticalSection的成員函數(shù)Unlock()來(lái)釋放臨界區(qū):critical_section.Unlock();

?

再通俗一點(diǎn)講,就是線程A執(zhí)行到critical_section.Lock();語(yǔ)句時(shí),如果其它線程(B)正在執(zhí)行critical_section.Lock();語(yǔ)句后且critical_section. Unlock();語(yǔ)句前的語(yǔ)句時(shí),線程A就會(huì)等待,直到線程B執(zhí)行完critical_section. Unlock();語(yǔ)句,線程A才會(huì)繼續(xù)執(zhí)行。

B、使用 CEvent 類(lèi)

  CEvent 類(lèi)提供了對(duì)事件的支持。事件是一個(gè)允許一個(gè)線程在某種情況發(fā)生時(shí),喚醒另外一個(gè)線程的同步對(duì)象。例如在某些網(wǎng)絡(luò)應(yīng)用程序中,一個(gè)線程(記為A)負(fù)責(zé)監(jiān)聽(tīng)通訊端口,另外一個(gè)線程(記為B)負(fù)責(zé)更新用戶(hù)數(shù)據(jù)。通過(guò)使用CEvent 類(lèi),線程A可以通知線程B何時(shí)更新用戶(hù)數(shù)據(jù)。每一個(gè)CEvent 對(duì)象可以有兩種狀態(tài):有信號(hào)狀態(tài)和無(wú)信號(hào)狀態(tài)。線程監(jiān)視位于其中的CEvent 類(lèi)對(duì)象的狀態(tài),并在相應(yīng)的時(shí)候采取相應(yīng)的操作。

  在MFC中,CEvent 類(lèi)對(duì)象有兩種類(lèi)型:人工事件和自動(dòng)事件。一個(gè)自動(dòng)CEvent 對(duì)象在被至少一個(gè)線程釋放后會(huì)自動(dòng)返回到無(wú)信號(hào)狀態(tài);而人工事件對(duì)象獲得信號(hào)后,釋放可利用線程,但直到調(diào)用成員函數(shù)ReSetEvent()才將其設(shè)置為無(wú)信號(hào)狀態(tài)。在創(chuàng)建CEvent 類(lèi)的對(duì)象時(shí),默認(rèn)創(chuàng)建的是自動(dòng)事件。 CEvent 類(lèi)的各成員函數(shù)的原型和參數(shù)說(shuō)明如下:

?

1、CEvent(BOOL bInitiallyOwn=FALSE,

????????? BOOL bManualReset=FALSE,

????????? LPCTSTR lpszName=NULL,

????????? LPSECURITY_ATTRIBUTES lpsaAttribute=NULL);

bInitiallyOwn:指定事件對(duì)象初始化狀態(tài),TRUE為有信號(hào),F(xiàn)ALSE為無(wú)信號(hào);

bManualReset:指定要?jiǎng)?chuàng)建的事件是屬于人工事件還是自動(dòng)事件。TRUE為人工事件,F(xiàn)ALSE為自動(dòng)事件;

后兩個(gè)參數(shù)一般設(shè)為NULL,在此不作過(guò)多說(shuō)明。

?

2、BOOL CEvent::SetEvent();

  將 CEvent 類(lèi)對(duì)象的狀態(tài)設(shè)置為有信號(hào)狀態(tài)。如果事件是人工事件,則 CEvent 類(lèi)對(duì)象保持為有信號(hào)狀態(tài),直到調(diào)用成員函數(shù)ResetEvent()將 其重新設(shè)為無(wú)信號(hào)狀態(tài)時(shí)為止。如果CEvent 類(lèi)對(duì)象為自動(dòng)事件,則在SetEvent()將事件設(shè)置為有信號(hào)狀態(tài)后,CEvent 類(lèi)對(duì)象由系統(tǒng)自動(dòng)重置為無(wú)信號(hào)狀態(tài)。

如果該函數(shù)執(zhí)行成功,則返回非零值,否則返回零。 3、BOOL CEvent::ResetEvent();

  該函數(shù)將事件的狀態(tài)設(shè)置為無(wú)信號(hào)狀態(tài),并保持該狀態(tài)直至SetEvent()被調(diào)用時(shí)為止。由于自動(dòng)事件是由系統(tǒng)自動(dòng)重置,故自動(dòng)事件不需要調(diào)用該函數(shù)。如果該函數(shù)執(zhí)行成功,返回非零值,否則返回零。我們一般通過(guò)調(diào)用WaitForSingleObject函數(shù)來(lái)監(jiān)視事件狀態(tài)。前面我們已經(jīng)介紹了該函數(shù)。由于語(yǔ)言描述的原因,CEvent 類(lèi)的理解確實(shí)有些難度,但您只要通過(guò)仔細(xì)玩味下面例程,多看幾遍就可理解。

例程9 MultiThread9

?

CEvent eventWriteD;

線程WriteD執(zhí)行到 WaitForSingleObject(eventWriteD.m_hObject,INFINITE);處等待,直到事件eventWriteD為有信號(hào)該線程才往下執(zhí)行,因?yàn)閑ventWriteD對(duì)象是自動(dòng)事件,則當(dāng)WaitForSingleObject()返回時(shí),系統(tǒng)自動(dòng)把eventWriteD對(duì)象重置為無(wú)信號(hào)狀態(tài)

??? CWinThread *pWriteD=AfxBeginThread(WriteD,

??????? &m_ctrlD,

??????? THREAD_PRIORITY_NORMAL,

??????? 0,

??????? CREATE_SUSPENDED);

??? pWriteD->ResumeThread();

?

C、使用CMutex 類(lèi)

互斥對(duì)象與臨界區(qū)對(duì)象很像.互斥對(duì)象與臨界區(qū)對(duì)象的不同在于:互斥對(duì)象可以在進(jìn)程間使用,而臨界區(qū)對(duì)象只能在同一進(jìn)程的各線程間使用。當(dāng)然,互斥對(duì)象也可以用于同一進(jìn)程的各個(gè)線程間,但是在這種情況下,使用臨界區(qū)會(huì)更節(jié)省系統(tǒng)資源,更有效率。

?

D、使用CSemaphore 類(lèi)? afxmt.h

  當(dāng)需要一個(gè)計(jì)數(shù)器來(lái)限制可以使用某個(gè)線程的數(shù)目時(shí),可以使用“信號(hào)量”對(duì)象。CSemaphore 類(lèi)的對(duì)象保存了對(duì)當(dāng)前訪問(wèn)某一指定資源的線程的計(jì)數(shù)值,該計(jì)數(shù)值是當(dāng)前還可以使用該資源的線程的數(shù)目。如果這個(gè)計(jì)數(shù)達(dá)到了零,則所有對(duì)這個(gè)CSemaphore 類(lèi)對(duì)象所控制的資源的訪問(wèn)嘗試都被放入到一個(gè)隊(duì)列中等待,直到超時(shí)或計(jì)數(shù)值不為零時(shí)為止。一個(gè)線程被釋放已訪問(wèn)了被保護(hù)的資源時(shí),計(jì)數(shù)值減1;一個(gè)線程完成了對(duì)被控共享資源的訪問(wèn)時(shí),計(jì)數(shù)值增1。這個(gè)被CSemaphore 類(lèi)對(duì)象所控制的資源可以同時(shí)接受訪問(wèn)的最大線程數(shù)在該對(duì)象的構(gòu)建函數(shù)中指定。

?

CSemaphore 類(lèi)的構(gòu)造函數(shù)原型及參數(shù)說(shuō)明如下:

?

CSemaphore (LONG lInitialCount=1,

??????????? LONG lMaxCount=1,

??????????? LPCTSTR pstrName=NULL,

??????????? LPSECURITY_ATTRIBUTES lpsaAttributes=NULL);

lInitialCount:信號(hào)量對(duì)象的初始計(jì)數(shù)值,即可訪問(wèn)線程數(shù)目的初始值;

lMaxCount:信號(hào)量對(duì)象計(jì)數(shù)值的最大值,該參數(shù)決定了同一時(shí)刻可訪問(wèn)由信號(hào)量保護(hù)的資源的線程最大數(shù)目;

后兩個(gè)參數(shù)在同一進(jìn)程中使用一般為NULL,不作過(guò)多討論;

  在用CSemaphore 類(lèi)的構(gòu)造函數(shù)創(chuàng)建信號(hào)量對(duì)象時(shí)要同時(shí)指出允許的最大資源計(jì)數(shù)和當(dāng)前可用資源計(jì)數(shù)。一般是將當(dāng)前可用資源計(jì)數(shù)設(shè)置為最大資源計(jì)數(shù),每增加一個(gè)線程對(duì)共享資源的訪問(wèn),當(dāng)前可用資源計(jì)數(shù)就會(huì)減1,只要當(dāng)前可用資源計(jì)數(shù)是大于0的,就可以發(fā)出信號(hào)量信號(hào)。但是當(dāng)前可用計(jì)數(shù)減小到0時(shí),則說(shuō)明當(dāng)前占用資源的線程數(shù)已經(jīng)達(dá)到了所允許的最大數(shù)目,不能再允許其它線程的進(jìn)入,此時(shí)的信號(hào)量信號(hào)將無(wú)法發(fā)出。線程在處理完共享資源后,應(yīng)在離開(kāi)的同時(shí)通過(guò)ReleaseSemaphore()函數(shù)將當(dāng)前可用資源數(shù)加1。

CSemaphore semaphoreWrite(2,2); //資源最多訪問(wèn)線程2個(gè),當(dāng)前可訪問(wèn)線程數(shù)2個(gè)

UINT WriteA(LPVOID pParam)

{

??? CEdit *pEdit=(CEdit*)pParam;

??? pEdit->SetWindowText("");

??? WaitForSingleObject(semaphoreWrite.m_hObject,INFINITE);

??? CString str;

??? for(int i=0;i<10;i++)

??? {

??????? pEdit->GetWindowText(str);

??????? g_Array[i]=''A'';

??????? str=str+g_Array[i];

??? ??? pEdit->SetWindowText(str);

??????? Sleep(1000);

??? }

??? ReleaseSemaphore(semaphoreWrite.m_hObject,1,NULL);

??? return 0;

}

在信號(hào)量對(duì)象有信號(hào)的狀態(tài)下,線程執(zhí)行到WaitForSingleObject語(yǔ)句處繼續(xù)執(zhí)行,同時(shí)可用線程數(shù)減1;若線程執(zhí)行到WaitForSingleObject語(yǔ)句時(shí)信號(hào)量對(duì)象無(wú)信號(hào),線程就在這里等待,直到信號(hào)量對(duì)象有信號(hào)線程才往下執(zhí)行。

?

#include

#include

#include

using namespacestd;

int nCount=50;???

DWORD ThreadID1;

DWORD ThreadID2;

DWORD ThreadID3;

HANDLE hMutex;

DWORD WINAPI TProc1(LPVOIDlParam)

{

??? while(nCount>0)

??? {

?????? Sleep(1);

?????? WaitForSingleObject(hMutex,INFINITE);

?????? printf("nCount=%d----線程n",nCount);

?????? nCount--;

?????? ReleaseMutex(hMutex);

??????

??? }

??? return 1;

}

DWORD WINAPI TProc2(LPVOIDlParam)

{

??? while(nCount>0)

??? {????? Sleep(1);

?????? WaitForSingleObject(hMutex,INFINITE);

?????? printf("nCount=%d----線程n",nCount);

?????? nCount--;

?????? ReleaseMutex(hMutex);

??? }

??? return 1;

}

?

?

int main(void)

{

??? hMutex=CreateMutex(NULL,NULL,NULL);

??? HANDLE h1=CreateThread(NULL,NULL,TProc1,NULL,NULL,&ThreadID1);

??? HANDLE h2=CreateThread(NULL,NULL,TProc2,NULL,NULL,&ThreadID2);

??? Sleep(5000);

??? return 0;

}

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車(chē)技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車(chē)工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車(chē)。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶(hù)希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱(chēng),數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱(chēng)"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉