事實上,Win32 API提供了_beginthreadex函數,可以讓使用者在底層啟動線程。總地來說,Win32 API提供的線程處理的介面,引用較為複雜。因此,在Win32 API的基礎上,MFC提供了處理線程的類和函數。其中,MFC提供處理線程的類為CWinThread類。CWinThread類使用執行緒區域儲存來管理在MFC環境中的線程的上下文資訊。
一般地說,使用者可以直接聲明CWinThread對象,但在許多情況下,可以讓MFC的全域函數AfxBeginThread來建立CWinThread對象。CWinThread類提供了幾個函數來對線程進行操作。例如下面的幾個函數。
CWinThread:: AfxBeginThread函數:用來建立進程。
CWinThread::CreateThread函數:用來啟動新的線程。
CWinThread::SuspendThread函數:用來掛起線程。
CWinThread::ResumeThread函數:用來恢複線程的執行。
此外,讀者還需知道,MFC中支援兩種類型的線程:工作者線程和使用介面執行緒。下面將為讀者詳細介紹這兩種線程的建立和使用。其區別在於:工作者線程常用於完成不要求使用者輸入的任務,如耗時計算、後台列印之類的任務。因此,其不需要有介面。工作者線程也適用於等待一個事件的發生。例如,從一個應用程式中接收資料,而不必要求使用者等待。
17.2.2 建立工作者線程
工作者線程可以說是並存執行的一個函數,其一般用來完成那些不需要使用者輸入的背景工作。例如Database Backup功能和網路連接狀態監視等功能。
比如,一個收費站的進口只有一個收費視窗在工作。該收費視窗正在處理正常的車輛收費工作,此時來了一個車隊。該車隊有許多車,需要花費很長時間來完成其收費工作。為了不使其他車輛阻塞,需要另外新開一個收費視窗,專門用於解決該車隊的收費。如果把正常收費的視窗看做主線程,這個新開的視窗就是工作者線程,17-2所示。
圖17-2 工作者線程
簡單地說,建立一個工作者線程就是實現一個控制函數,並將其地址傳給適當形式的AfxBeginThread函數的問題。一般來說,工作者線程形式的AfxBeginThread的聲明格式如下:
CWinThread* AFXAPI AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority,
UINT nStackSize,
DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs
);
其中,主要參數說明如下所述。
pfunThreadProc參數:指定線程的入口函數地址。
pParam參數:指定傳遞給線程的參數。
簡單地說,前兩個參數是控制函數的地址和要傳送給控制函數的參數。其餘的參數可以指定線程的優先順序、棧大小、建立後是立即掛起還是立即運行。最後的參數指定線程的安全屬性,其預設值為NULL,即表示該線程將繼承調用線程的安全屬性。
提示:該函數調用成功的傳回值是CWinThread類的指標。可以通過它實現對線程的控制。線上程函數返回時線程將被結束,線上程內部可以利用void AfxEndThread(UINT nExitCode);結束線程。其中,nExitCode為退出碼。
工作者線程一旦啟動,就開始執行控制函數。線程結束,控制函數也就結束了。線程式控制制函數的原型如下:
UINT MyControllingFunction(LPVOID pParam);
其中的函數名並不是固定的那個函數名,而是使用者自訂的函數名,可以為任何合法的命名。如使用者自訂名為MyThread。
例如,下面語句建立了一個工作者線程,其中指定線程的入口函數地址為function函數的地址。
UINT function(LPVOID pParam )
{
while(true)
{
printf("Welcome to 21 Visual C++");
Sleep(1000);
printf("\t");
return 0;
}
}
AfxBeginThread(function, NULL); //用於建立工作者線程