摘要:本文主要以mfc線程為主題展開的概述,詳細(xì)介紹了線程,線程與函數(shù)以及實(shí)例來說明,下面我們一起來看看原文。
線程簡介
我們知道一般情況程序中的代碼都是按順序從頭開始一行一行的執(zhí)行以最后。中間不能出現(xiàn)同時執(zhí)行的情況。比如一段代碼調(diào)用兩個函數(shù)
FunOne();
FunTwo();
只要當(dāng)函數(shù)FunOne中的代碼執(zhí)行完才返回來執(zhí)行FunTwo.假如邏輯上是有先后順序那還真只能這樣按順序執(zhí)行下來。不過有假如FunOne與FunTwo沒有邏輯先后順序,是相互獨(dú)立的。比如兩個函數(shù)分別處理兩不同的文件one.text與two.txt.
這種情形就可以用到線程,弄兩個線程去執(zhí)行這兩函數(shù)。這樣兩函數(shù)同時執(zhí)行,提高了效率(如果單核的CPU可能沒有真正的并行效果不明顯,那多核CPU執(zhí)行多線程那是能夠真正達(dá)到并行執(zhí)行,效果很明顯的)。
實(shí)際上可以這樣簡單的理解線程,它是CPU的調(diào)度單位。而一個線程是對應(yīng)一個函數(shù)。所以別把一個線程想得太復(fù)雜,就只是執(zhí)行個函數(shù)而已。只不過執(zhí)行的時候是并行執(zhí)行罷了。如果只是簡單的幾個線程不涉及使用共同的資源,沒其他啥關(guān)聯(lián)。就完全跟簡單的執(zhí)行一個函數(shù)類似。只是如果多個線程間關(guān)系復(fù)雜就會涉及到啥同步問題,那樣就有很多復(fù)雜的細(xì)節(jié)性問題。
線程間通信的方式
方式一:全局變量,各線程通過修改全局變量傳遞信息,通過循環(huán)檢測查看信息。 方式二:消息傳遞,通過windows消息機(jī)制傳遞。
方式一問題主要有兩個:第一是全局變量過多,不便于管理;第二個是循環(huán)檢測過于緩慢,并且較不靈活,不能夠迅速響應(yīng)變化。
MFC中存在三種線程
A、 Ui線程:通過創(chuàng)建窗口得到,具備標(biāo)準(zhǔn)窗口的功能。
B、 工作者線程:通過CreateThread函數(shù)直接創(chuàng)建,不具備消息隊(duì)列。
C、 帶消息隊(duì)列的工作者線程:通過繼承CWinThread得到,具備消息隊(duì)列。
A種和C種線程使用消息隊(duì)列,對于使用者來說,這兩種線程需要自己本身或其他線程向其發(fā)送消息,才進(jìn)行相應(yīng)工作,否則保持靜默狀態(tài),該兩種線程擅長實(shí)時處理外部信號。 B種線程不使用消息隊(duì)列,可以用單個函數(shù)作為其線程的本體,適合處理步驟相對固定的算法。
線程與函數(shù)
線程函數(shù)必須是全局函數(shù),或者是類的靜態(tài)成員函數(shù),因?yàn)榉庆o態(tài)成員函數(shù)有this指針,而在進(jìn)程中無法訪問此指針。
但是靜態(tài)成員函數(shù)只能訪問靜態(tài)成員,解決此問題途徑:
1. 就是在調(diào)用靜態(tài)成員函數(shù)時將this指針作為參數(shù)傳入,通過該指針訪問非靜態(tài)成員。
2. 不將線程函數(shù)定義為類的靜態(tài)成員函數(shù),而是定義為類的友元函數(shù),這樣函數(shù)線程也可以有類成員函數(shù)相同的權(quán)限。
最簡單示例
線程分工作線程與界面線程。這里就以工作線程為例
1.先來看個MFC中的創(chuàng)建線程的簡單例子。
UINT ThreadFun(LPVOID pParam){ //線程要調(diào)用的函數(shù)
MessageBox(NULL,_T(“i am called by a thread.”), _T(“thread func”),MB_OK);
}
?。海篈fxBeginThread(ThreadFun, NULL); //這就是創(chuàng)建一個線程并執(zhí)行了,調(diào)用上面的函數(shù)彈出一個對話框。
2.示例分析
上面的線程是簡單的不能再簡單了吧。下面從兩個來分析下。
a.首先是被調(diào)用的函數(shù)有啥講究不? 當(dāng)然有,被線程用到的函數(shù)格式必須是統(tǒng)一的,返回類型必須是UINT,函數(shù)只能有一個參數(shù)LPVOID.其中UINT就是個無符號的整形,LPVOID是void*,所以這個參數(shù)表示可以傳任何類型的指針過來的。
b.函數(shù)AfxBeginThread的分析。
這個函數(shù)還有返回值CWinThread*的,如果你只是簡單的創(chuàng)建一個線程并執(zhí)行,就不用管了。但如果想要對創(chuàng)建的線程做其他操作就必須這樣寫。
CWinThread* pThread = ::AfxBeginThread(ThreadFun, NULL); //接下來做啥就直接調(diào)用pThead就行。
另外函數(shù)AfxBeginThread的參數(shù)有很多個,但很多都有默認(rèn)值。下面是完整的參數(shù)
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc, //一個函數(shù)指針
LPVOID pParam, //void*類型的指針,可以傳任何種類指針過來。
int nPriority = THREAD_PRIORITY_NORMAL, //線程優(yōu)先級
UNT nStackSize = 0, //分配堆棧大小
DWORD dwCreateFlags = 0, //表示線程創(chuàng)建后是立即執(zhí)行還是等會執(zhí)行
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL //線程安全屬性指針
?。?//用于創(chuàng)建工作者線程
上面的參數(shù)我們用的最多的是3個,其他一盤都默認(rèn)值。
AFX_THREADPROC pfnThreadProc //函數(shù)指針肯定是必須要指定的,不然線程執(zhí)行哪個函數(shù)去啊
LPVOID pParam //這是傳給上面指定函數(shù)的參數(shù)。如果被調(diào)用的函數(shù)需要啥參數(shù)就只能在這里指定了。
DWORD dwCreateFlags //默認(rèn)值為0表示創(chuàng)建線程后立即執(zhí)行。如果是CREATE_SUSPEND則表示創(chuàng)建好后先掛起。必須通過ResumeThread來執(zhí)行。
評論
查看更多