WINDOWS下的多線程編程可以說是一個很深入的話題。有的人說,是否掌握多線程,是程式高手與一業餘的區別!今天終於把想了很久的一本書從圖書館請了回來,名:《WINDOWS環境中的多線程實現》也是一個寫自己的經驗的一本書,我覺得自己很適合看這種書,但是,又不太喜歡其中的常式,總覺得本來可以看簡單的東西,他非要搞點風馬牛不相干的東西過來,使多線程的主體地位反而被充淡了。所以,結合他的思想,再看了看MSDN,我自己改造了一下,雖然簡單,但是可以很容易理解,而且可以很快的應用到自己的程式設計中去,我覺得單純的講多線程是沒有什麼力量的,非得在實際應用中才能體會到它的好處和麻煩。比方說用在網路的SOCKET編程中。閑話不扯,下面我先來說一些基本概念:
一:什麼是進程,線程:
“進程”是應用程式的執行執行個體。例如,雙擊“記事本”表徵圖時,將啟動運行“記事本”的進程。
“線程”是進程內的執行路徑。啟動“記事本”時,作業系統建立進程並開始執行該進程的主線程。此線程終止時,進程也終止。啟動代碼以函數地址的形式將此主線程提供給作業系統。通常是所提供的 main 函數或 WinMain 函數的地址。
但是你也可以在主線程下建立子(其它)線程,為了完成一些背景處理工作。要處理後台或維護任務但又不想讓使用者等待完成這些任務時,您可能希望進行此操作。MFC中所有線程都由CWndThread來表示,但是在大多數情況下,我們不必顯式的建立這些對象,而可以用AfxBeginTread函數來建立一個線程;它的定義如下:CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
CWinThread* AfxBeginThread(
CRuntimeClass* pThreadClass,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
MFC中線程可以分為兩種,
一:一個是使用介面執行緒,主要用來完成與使用者輸入有關的工作和響應使用者事件。為了實現這一功能,往往會有一個叫做訊息泵的機制,例如:WinApp就是使用介面執行緒對象的一個執行個體,做為主線程用來處理使用者訊息。
二:另一個是輔助線程或者稱做為背景工作執行緒。它主要是為了完成一些不需要使用者輸入的操作。
下面我通過一個例子來說明一個背景工作執行緒是如何建立的。
1:建立MFC工程,帶文檔/視圖結構。然後在菜單中加入兩項,一個代表多線程,一個代表單線程;
2:建立如下的類結構:
3:OnMThead()中建立子線程void CWorkThreadView::OnMThead()
{
// TODO: Add your command handler code here
pThread = AfxBeginThread( Calculate, this );
AfxMessageBox("哈哈,我是多線程中的主線程,你會看到我的子線程和我一起出來呢!");
pSubThread = AfxBeginThread( SubThread, this );
}
4:上面的SubThread是另一個進程的處理函數UINT SubThread( LPVOID pParam )
{
CWorkThreadView *pView = (CWorkThreadView*)pParam;
pView->PostMessage(WM_SUBTHREADMSG,NULL,0);
return 0;
}
5:而在CWorkThreadView類中處理WM_SUBTHREADMSG訊息的函數是:DealSubThreadMsgvoid CWorkThreadView::DealSubThreadMsg( WPARAM wParam, LPARAM lParam )
{
AfxMessageBox("呵呵,一個子線程向我發了訊息了!");
}
6:下面,大家就應該猜出運行結果了吧,是不是很簡單啊。呵呵,現在總結一下如何建立背景工作執行緒:
* 啟動進程 AfxBeginThread
* 實現控制函數
這裡只是一個簡單的建立背景工作執行緒的方法,可以說只是個入門,多線程的精華並不在這裡,而是在後來的線程通訊,互斥訪問,訊號量等細節,所以,多線程!我才剛剛上路呢!