天天看點

VC啟動一個新線程的三種方法

第一種AfxBeginThread()

用AfxBeginThread()函數來建立一個新線程來執行任務,工作者線程的AfxBeginThread的原型如下:

CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,

  LPVOID lParam,

  int nPriority = THREAD_PRIORITY_NORMAL,

  UINT nStackSize = 0,

  DWORD dwCreateFlags = 0,

  LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL

  );//用于建立工作者線程

傳回值: 成功時傳回一個指向新線程的線程對象的指針,否則NULL。

pfnThreadProc : 線程的入口函數,聲明一定要如下: UINT MyThreadFunction(LPVOID pParam),不能設定為NULL;

pParam : 傳遞入線程的參數,注意它的類型為:LPVOID,是以我們可以傳遞一個結構體入線程.

nPriority : 線程的優先級,一般設定為 0 .讓它和主線程具有共同的優先級.

nStackSize : 指定新建立的線程的棧的大小.如果為 0,新建立的線程具有和主線程一樣的大小的棧

dwCreateFlags : 指定建立線程以後,線程有怎麼樣的标志.可以指定兩個值:

CREATE_SUSPENDED : 線程建立以後,會處于挂起狀态,直到調用:ResumeThread

0 : 建立線程後就開始運作.

lpSecurityAttrs : 指向一個 SECURITY_ATTRIBUTES 的結構體,用它來标志新建立線程的安全性.如果為 NULL,

那麼新建立的線程就具有和主線程一樣的安全性.

如果要線上程内結束線程,可以線上程内調用 AfxEndThread.

一般直接用AfxBeginThread(ThreadProc,this);

示例:

UINT  myproc(LPVOID  lParam)
{
CITTDlg *pWnd = (CITTDlg *)lParam;         //将視窗指針賦給無類型指針
pWnd->KMeansSegment();                         //要執行的函數
return 1;
}

void CITTDlg::KMeansSegment()
{
// 主要處理函數在這裡寫
}

void CITTDlg::OnKMeansSegment()             //按鈕點選執行
{

AfxBeginThread(myproc, (LPVOID)this);//啟動新的線程

}
           

注意,工作者線程的函數必須是全局函數或靜态成員函數,不能是普通的成員函數。

第二種CreateThread()

函數原型為:HANDLE CreateThread(

                           NULL,  // 沒有安全描述符

                           0,  // 預設線程棧的大小

                           MyThreadProc,  // 線程函數指針,即函數名

                           (LPVOID)&n,  // 傳遞參數

                           NULL,  // 沒有附加屬性

                           NULL  // 不需要獲得線程号碼

                           );

CreatThread,它傳回的是一個句柄;如果不需要再監視線程,則用CloseHandle()關閉線程句柄。

線程的函數必須定義為: DWORD WINAPI   MyThreadProc(LPVOID pParameter);

下面示範多線程操作控件,點選一個Button然後運作一個線程,将字元串顯示在CEdit控件裡面;

示例:

.h頭檔案

struct hS
    {
        CString Tmp;
        CTestDlg *hWnd;
    };//定義全局結構體,用來傳遞自定義消息

DWORD WINAPI ThreadProc(LPVOIDlpParam);//線程函數聲明,全局函數

public:
    CString chtmp;
    struct hS    *hTmp;

protected:
   HANDLE m_hThread;//線程句柄
   CEdit  m_Edit;

.cpp實作檔案

//線程執行函數

DWORD WINAPI   ThreadProc(LPVOID lpParam)
{
//在這裡寫處理函數
        struct hS *Tmp2;
        Tmp2 = (hS*)lpParam;
// 操作:
       Tmp2->hWnd->m_Edit.SetWindowText( (LPTSTR)Tmp2->Tmp );
}

void CTestDlg::OnBnClickedButton1()
{
    hTmp->Tmp = chtmp;
    hTmp->hWnd = this;//關鍵是把this指針傳進去
   m_hThread =CreateThread(NULL,0,ThreadProc,hTmp,0,NULL);//建立新線程
   CloseHandle(m_hThread );
}
           

用CreateThread()函數建立線程将傳回一個線程句柄,通過該句柄你可以控制和操作該線程,當你不用時可以一建立該線程後就關閉該句柄,有專門的函CloseHandle()。關閉句柄不代表關閉線程,隻是你不能在外部控制該線程(比如,提前結束,更改優先級等)。線上程結束後,系統将自動清理線程資源,但并不自動關閉該句柄,是以線程結束後要記得關閉該句柄。  

第三種_beginthread()

函數原型為:intptr_t  _beginthread(

                                                              void( *start_address )( void * ),  //指向新線程調用的函數的起始位址

                                                              unsigned stack_size,                  //堆棧大小,設定0為系統預設值

                                                              void *arglist                                  //傳遞給線程函數的參數,沒有則為NULL

                                                             );

傳回值:

假如成功,函數将會傳回一個新線程的句柄,使用者可以像這樣聲明一個句柄變量存儲傳回值:

  HANDLE hStdOut = _beginthread( CheckKey, 0, NULL )。如果失敗_beginthread将傳回-1。 所在庫檔案:

#include <process.h>

線程函數的定義:

對于_beginthread()建立的線程,其線程函數定義為:

void ThreadPro(void * pArguments );

_beginthreadex()為_beginthread()的更新版。

總結: AfxBeginThread是MFC的全局函數,是對CreateThread的封裝。  CreateThread是Win32 API函數,AfxBeginThread最終要調到CreateThread。而_beginthread是C的運作庫函數。

繼續閱讀