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