基于VC++的多線程通信程序設(shè)計(jì)論文
介紹了Windows多線程技術(shù)、多線程間通信、以及多線程通信程序設(shè)計(jì)的主要函數(shù),然后在前面關(guān)鍵技術(shù)的基礎(chǔ)上,采用VC++ 6.0 為開(kāi)發(fā)平臺(tái), 實(shí)現(xiàn)了一個(gè)基于VC++的多線程局域網(wǎng)聊天程序。
在多任務(wù)Windows編程中,為了提高代碼的時(shí)、空效率,廣泛采取后臺(tái)程序和前臺(tái)程序,而前臺(tái)任務(wù)及后臺(tái)任務(wù)是通過(guò)多線程技術(shù)來(lái)實(shí)現(xiàn),從而線程間的通信就變得極為重要。Visual C++對(duì)Windwos線程和消息的多任務(wù)機(jī)制提供了強(qiáng)有力的支持,并封裝了大量的通信函數(shù),給多線程通信程序編程帶來(lái)了很大的便利。
1、多線程技術(shù)概述
多線程在Windows編程中是一個(gè)比較重要的概念。所謂多線程,即在同一個(gè)程序中可以同時(shí)執(zhí)行多個(gè)任務(wù)。這意味著,編程者可以將整個(gè)任務(wù)分成幾個(gè)線程,然后讓操作系統(tǒng)同時(shí)執(zhí)行,從而提高程序的執(zhí)行效率。一般線程被分為兩種:用戶界面線程和工作線程(又稱為后臺(tái)線程)。
1.1 創(chuàng)建線程與終止線程
創(chuàng)建線程的過(guò)程可以分成兩大步驟,首先編寫(xiě)線程函數(shù),然后創(chuàng)建線程,并將其參數(shù)線程函數(shù)地址指向剛剛編寫(xiě)的線程函數(shù)。線程函數(shù)的退出,除了使用退出函數(shù)處理外,大都是隨著程序的結(jié)束而退出。
1.2 線程同步
多線程提高了程序執(zhí)行的效率,提高了編程的靈活性,但同時(shí)也引入了新的問(wèn)題。線程之間經(jīng)常要同時(shí)訪問(wèn)一些資源,因此對(duì)共享資源進(jìn)行訪問(wèn)引起沖突是不可避免的。另外,在Windwos的消息驅(qū)動(dòng)方式下,必須某個(gè)事件的發(fā)生了,才可以執(zhí)行某個(gè)線程,為了解決上述問(wèn)題,必須引入線程同步的概念。Win32 API提供了多種同步控制對(duì)象,包括臨界區(qū)、互斥對(duì)象、信號(hào)量和事件。
2、多線程間通信
一般而言,應(yīng)用程序中的一個(gè)次要線程總是為主線程執(zhí)行特定的任務(wù),這樣,主線程和次要線程間必定有一個(gè)信息傳遞的渠道,也就是主線程和次要線程間要進(jìn)行通信。這種線程間的通信不但是難以避免的,而且在多線程編程中也是復(fù)雜和頻繁的。多線程間通信可以采用全局變量、自定義消息、事件對(duì)象通信。
1) 使用全局變量進(jìn)行通信
由于屬于同一個(gè)進(jìn)程的各個(gè)線程共享操作系統(tǒng)分配該進(jìn)程的資源,故解決線程間通信最簡(jiǎn)單的一種方法是使用全局變量。對(duì)于標(biāo)準(zhǔn)類型的全局變量,可以使用volatile修飾符,它告訴編譯器無(wú)需對(duì)該變量作任何的優(yōu)化,即無(wú)需將它放到一個(gè)寄存器中,并且該值可被外部改變。如果線程間所需傳遞的信息較復(fù)雜,可以定義一個(gè)結(jié)構(gòu),通過(guò)傳遞指向該結(jié)構(gòu)的指針進(jìn)行傳遞信息。
2) 使用自定義消息進(jìn)行通信
可以在一個(gè)線程的執(zhí)行函數(shù)中向另一個(gè)線程發(fā)送自定義的消息來(lái)達(dá)到通信的目的。一個(gè)線程向另外一個(gè)線程發(fā)送消息是通過(guò)操作系統(tǒng)實(shí)現(xiàn)的。利用Windows操作系統(tǒng)的消息驅(qū)動(dòng)機(jī)制,當(dāng)一個(gè)線程發(fā)出一條消息時(shí),操作系統(tǒng)首先接收到該消息,然后把該消息轉(zhuǎn)發(fā)給目標(biāo)線程,接收消息的線程必須已經(jīng)建立了消息循環(huán)。
3) 使用事件對(duì)象進(jìn)行通信
在線程之間傳送信號(hào)的一種比較復(fù)雜的方法是使用享件對(duì)象,在MFC中有一個(gè)事件類CEvent。一個(gè)事件對(duì)象可以處于兩種狀態(tài)的一種:信號(hào)態(tài)和非信號(hào)態(tài)。線程能夠監(jiān)視處于信號(hào)態(tài)的事件,以便在適當(dāng)?shù)臅r(shí)間執(zhí)行對(duì)事件的操作。
3、多線程通信程序設(shè)計(jì)
3.1 重要函數(shù)
1) Win32 API對(duì)多線程編程的支持
Win32提供了一系列的API函數(shù)來(lái)完成線程的創(chuàng)建、掛起、恢復(fù)、終結(jié)以及通信等工作。下面將選取其中的一些重要函數(shù)進(jìn)行說(shuō)明。
、貶ANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
該函數(shù)在其調(diào)用進(jìn)程的進(jìn)程空間里創(chuàng)建一個(gè)新的線程,并返回已建線程的句柄,如果創(chuàng)建成功則返回線程的句柄,否則返回NULL。
、贒WORD SuspendThread(HANDLE hThread);
該函數(shù)用于掛起指定的線程,如果函數(shù)執(zhí)行成功,則線程的執(zhí)行被終止。
、跠WORD ResumeThread(HANDLE hThread);
該函數(shù)用于結(jié)束線程的掛起狀態(tài),執(zhí)行線程。
、躒OID ExitThread(DWORD dwExitCode);
該函數(shù)用于線程終結(jié)自身的執(zhí)行,主要在線程的執(zhí)行函數(shù)中被調(diào)用。其中參數(shù)dwExitCode用來(lái)設(shè)置線程的退出碼。
、軧OOL TerminateThread(HANDLE hThread,DWORD dwExitCode);
一般情況下,線程運(yùn)行結(jié)束之后,線程函數(shù)正常返回,但是應(yīng)用程序可以調(diào)用TerminateThread強(qiáng)行終止某一線程的執(zhí)行。使用TerminateThread()終止某個(gè)線程的執(zhí)行是不安全的,可能會(huì)引起系統(tǒng)不穩(wěn)定;雖然該函數(shù)立即終止線程的.執(zhí)行,但并不釋放線程所占用的資源。因此,一般不建議使用該函數(shù)。
、轇OOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM lParam);
該函數(shù)將一條消息放入到指定線程的消息隊(duì)列中,并且不等到消息被該線程處理時(shí)便返回。調(diào)用該函數(shù)時(shí),如果即將接收消息的線程沒(méi)有創(chuàng)建消息循環(huán),則該函數(shù)執(zhí)行失敗。
2) MFC對(duì)多線程編程的支持
MFC中有兩類線程,分別稱之為工作者線程和用戶界面線程。二者的主要區(qū)別在于工作者線程沒(méi)有消息循環(huán),而用戶界面線程有自己的消息隊(duì)列和消息循環(huán)。
工作者線程沒(méi)有消息機(jī)制,通常用來(lái)執(zhí)行后臺(tái)計(jì)算和維護(hù)任務(wù),如冗長(zhǎng)的計(jì)算過(guò)程,打印機(jī)的后臺(tái)打印等。用戶界面線程一般用于處理獨(dú)立于其他線程執(zhí)行之外的用戶輸入,響應(yīng)用戶及系統(tǒng)所產(chǎn)生的事件和消息等。但對(duì)于Win32的API編程而言,這兩種線程是沒(méi)有區(qū)別的,它們都只需線程的啟動(dòng)地址即可啟動(dòng)線程來(lái)執(zhí)行任務(wù)。
在MFC中,一般用全局函數(shù)AfxBeginThread()來(lái)創(chuàng)建并初始化一個(gè)線程的運(yùn)行,該函數(shù)有兩種重載形式,分別用于創(chuàng)建工作者線程和用戶界面線程。兩種重載函數(shù)原型和參數(shù)分別說(shuō)明如下:
①CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,LPVOID pParam,
nPriority=THREAD_PRIORITY_NORMAL, UINT nStackSize=0,
DWORD dwCreateFlags=0,LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
、贑WinThread* AfxBeginThread(CRuntimeClass* pThreadClass,
int nPriority=THREAD_PRIORITY_NORMAL,UINT nStackSize=0,
DWORD dwCreateFlags=0, LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
一般情況下,調(diào)用AfxBeginThread()來(lái)一次性地創(chuàng)建并啟動(dòng)一個(gè)線程,但是也可以通過(guò)兩步法來(lái)創(chuàng)建線程:首先創(chuàng)建CWinThread類的一個(gè)對(duì)象,然后調(diào)用該對(duì)象的成員函數(shù)CreateThread()來(lái)啟動(dòng)該線程。
、踲irtual BOOL CWinThread::InitInstance();
重載該函數(shù)以控制用戶界面線程實(shí)例的初始化。初始化成功則返回非0值,否則返回0。用戶界面線程經(jīng)常重載該函數(shù),工作者線程一般不使用InitInstance()。
、躹irtual int CWinThread::ExitInstance();
在線程終結(jié)前重載該函數(shù)進(jìn)行一些必要的清理工作。該函數(shù)返回線程的退出碼,0表示執(zhí)行成功,非0值用來(lái)標(biāo)識(shí)各種錯(cuò)誤。同InitInstance()成員函數(shù)一樣,該函數(shù)也只適用于用戶界面線程。
3.2 VC++下多線程局域網(wǎng)聊天程序
聊天程序是現(xiàn)代生活中不可缺少的通信工具,為了在局域網(wǎng)中實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)的實(shí)時(shí)通信,在VC++的編程環(huán)境中,利用套接字庫(kù)技術(shù)和多線程編程技術(shù)實(shí)現(xiàn)聊天程序。
1) 界面設(shè)計(jì)。界面設(shè)計(jì)如圖1所示。
2) 函數(shù)
void CMyQQDlg:: SendMsg() //發(fā)送消息
void CMyQQDlg:: SendFile() //發(fā)送文件
void CMyQQDlg:: Caputer() //抓取屏幕
void CMyQQDlg::AddMsgList(CString IP,CString str) //添加信息于LISTBOX 控件中
CString CMyQQDlg::GetError(DWORD error) //返回錯(cuò)誤信息
int CMyQQDlg::GetLocalHostName(CString &sHostName) //獲得本地計(jì)算機(jī)名稱
int CMyQQDlg::GetIpAddress(const CString &sHostName, CString &sIpAddress)//獲得本地IP
int CMyQQDlg::GetNamebyAddress(const CString &IpAddress,CString &sYouName)//獲得對(duì)方計(jì)算機(jī)名稱
3) 線程啟動(dòng)
pThreadLisen=::AfxBeginThread(_ListenTcpThread,this); //開(kāi)始TCP線程
pThreadLisen=::AfxBeginThread(_UDPThread,this); //開(kāi)始UDP線程
4) 服務(wù)器線程
UINT _ListenTcpThread(LPVOID lparam) //TCP監(jiān)聽(tīng)線程
UINT _UDPThread(LPVOID lparam) //UDP接受信息線程開(kāi)始
5) 客戶端線程
UINT _SendFileThread(LPVOID lparam) //發(fā)送文件線程
UINT _SendMsgThread(LPVOID lparam) //TCP發(fā)送信息線程
UINT _SendMsgUdpThread(LPVOID lparam) //UDP發(fā)送信息
UINT _ThreadCapture(LPVOID lparam) //抓取對(duì)方屏幕線程
以上程序在Windows XP, Microsoft Visual C++6.0中編譯執(zhí)行通過(guò)。
4、結(jié)束語(yǔ)
要設(shè)計(jì)出性能較好的多線程通信程序,不僅需要對(duì)操作系統(tǒng)的處理過(guò)程很清楚,還需要對(duì)VC++的線程處理函數(shù)十分了解,并對(duì)具體應(yīng)用中各線程的關(guān)系非常清楚,以利于在應(yīng)用程序中控制同步事件的發(fā)生,避免出現(xiàn)死鎖或不能同步處理的現(xiàn)象。
【基于VC++的多線程通信程序設(shè)計(jì)論文】相關(guān)文章:
1.基于Vxworks實(shí)時(shí)操作系統(tǒng)的串口通信程序設(shè)計(jì)與實(shí)現(xiàn)
2.基于AMF的Android數(shù)據(jù)通信論文
3.關(guān)于多線程技術(shù)在數(shù)據(jù)通信中的運(yùn)用分析論文
5.淺談基于單片機(jī)的數(shù)據(jù)串口通信研究論文