AfxBeginThread的介紹/基本用法和Window多線程使用詳解

AfxBeginThread 
   用戶界面線程和工做者線程都是由AfxBeginThread建立的。如今,考察該函數:MFC提供了兩個重載版的AfxBeginThread,一個用於用戶界面線程,另外一個用於工做者線程,分別有以下的原型和過程:
編程

用戶界面線程的AfxBeginThread 
用戶界面線程的AfxBeginThread的原型以下:
windows

[cpp] view plain copyapi

  1. CWinThread* AFXAPI AfxBeginThread(  安全

  2. CRuntimeClass* pThreadClass,  微信

  3. int nPriority,   多線程

  4. UINT nStackSize,   ide

  5. DWORD dwCreateFlags,  函數

  6. LPSECURITY_ATTRIBUTES lpSecurityAttrs)  this

其中:
參數1是從CWinThread派生的RUNTIME_CLASS類;
參數2指定線程優先級,若是爲0,則與建立該線程的線程相同;
參數3指定線程的堆棧大小,若是爲0,則與建立該線程的線程相同;
參數4是一個建立標識,若是是CREATE_SUSPENDED,則在懸掛狀態建立線程,在線程建立後線程掛起,不然線程在建立後開始線程的執行。
參數5表示線程的安全屬性,NT下有用。 url


工做者線程的AfxBeginThread 
工做者線程的AfxBeginThread的原型以下:

[cpp] view plain copy

  1. CWinThread* AFXAPI AfxBeginThread(  

  2. AFX_THREADPROC pfnThreadProc,   

  3. LPVOID pParam,  

  4. int nPriority,   

  5. UINT nStackSize,   

  6. DWORD dwCreateFlags,  

  7. LPSECURITY_ATTRIBUTES lpSecurityAttrs)  

其中:
參數1  線程的入口函數,聲明必定要以下: UINT MyThreadFunction( LPVOID pParam );
參數2 傳遞入線程的參數,注意它的類型爲:LPVOID,因此咱們能夠傳遞一個結構體入線程.
參數三、四、5分別指定線程的優先級、堆棧大小、建立標識、安全屬性,含義同用戶界面線程。 


附錄A

結束線程的兩種方式
     當你在後臺用線程來打印一些圖形時.有時在打印一部分後,你但願能夠停下來,那麼此如何讓線程中止呢.下

面會詳細的向你解釋要結束線程的兩種方式
     1 : 這是最簡單的方式,也就是讓線程函數執行完成,此時線程正常結束.它會返回一個值,通常0是成功結束,

固然你能夠定義本身的認爲合適的值來表明線程成功執行.在線程內調用AfxEndThread將會直接結束線程,此時線程的一切資源都會被回收.
     2 : 若是你想讓別一個線程B來結束線程A,那麼,你就須要在這兩個線程中傳遞信息.不論是工做者線程仍是界面線程,若是你想在線程結束後獲得它的確結果,那麼你能夠調用     ::GetExitCodeThread函數

線程的三種狀態:

運行一個線程:

m_lpThread = AfxBeginThread( Thread, NULL, THREAD_PRIORITY_NORMAL,

                                              0, CREATE_SUSPENDED );//其中Thread成員函數要設置爲static類型

暫停一個線程:

m_lpThread ->SuspendThread();或者sleep(1000);//讓線程睡眠

喚醒一個線程:

m_lpThread ->ResumeThread();

經驗總結: 

     仍是老師的那個項目,之前因爲計算量太大,致使程序常常出現假死的現象,由於程序只有一個線程,該線程主要用於處理計算上了,而對於消息隊列的響應被忽略了。所以解決的辦法就是用兩個線程,一個線程用於計算,一個線程用於處理消息。
      到網上找了一些資料,發如今MFC中把線程分爲兩類,一類爲界面線程,一類爲工做線程。二者的區別在於前都可以處理消息響應,然後者則不能。對於該項目來講,只要把計算的過程放到一個工做線程裏來進行就能夠了。
    如今先試一下,我新建了一個對話框,上面添加兩個按鈕,一個是start 一個是dialog。前者用於開始計算,然後者則彈出一個消息框。而後向該對話框裏面添加一個死循環的函數

[cpp] view plain copy

  1. UINT CMultithreadDlg::jisuan(LPVOID lpParam)  

  2. {  

  3. int i = 1;  

  4. for (;;)  

  5.    i+=i;  

  6. return 0;  

  7. }  

    而後在start按鈕的響應函數上添加上jisuan(NULL);便可,如今運行程序,按下start按鈕後,能夠看到CPU使用率漲到了100%,這個時候再按dialog按鈕無反應,拖動關閉窗口均無效。這就是前面提到的假死現象(其實是真死,由於死循環了,若是不是死循環,而只是計算量太大才是假死)。


    下面用多線程的方法來解決,在start按鈕的響應函數改成
   CWinThread* mythread = AfxBeginThread(   jisuan,   NULL,   THREAD_PRIORITY_NORMAL,   0,   0,   NULL   );
    運行,結果發現有錯error C2665: 'AfxBeginThread' : none of the 2 overloads can convert parameter 1 from type 'unsigned int (void *)' Generating Code...
      我就納悶了,函數指針是對的啊,原來 線程函數能夠且必須是全局函數或者是靜態成員函數。因此咱們在線程函數的聲明中改成 static UINT jisuan(LPVOID lpParam);便可,而後運行程序,這時點擊start,待CPU漲至100%後,點擊dialog,彈出對話框了,拖動、關閉窗口均沒問題了。

     其實上面的那個AfxBeginThread,除前面兩個參數外,後面的都是默認參數,能夠省略。而必須有的這兩個參數,一個是線程函數的指針,一個是傳遞給這個函數的參數。實際中咱們常常這樣用 AfxBeginThread(ThreadProc,this);//把this傳過去,就能夠調用類的成員了. 這樣線程函數就可使用和操做類的成員了。千萬要注意線程函數是靜態類函數成員。

    線程是建立了,可是若是中途要暫停該怎麼作呢?
    咱們在建立線程的時候得到了一個CWinThread的指針,這是一個指向線程對象的指針,CWinThread類裏面就有暫停與恢復的函數,下面我就演示一下。在原來的程序上進行改動。向對話框類裏面添加一個CWinThread* 的成員變量,不用初始化爲NULL,這樣會報錯的,由於它只能經過AfxBeginThread函數得到。把start裏面的聲明去掉。
      而後添加一個 pause 按鈕向其響應函數裏面添加代碼 mythread->SuspendThread();   再添加一個 resume按鈕,向其響應函數裏面添加 mythread->ResumeThread();
    再運行程序,咱們start以後,按下pause能夠看到CPU恢復正常,而後resume,CPU又漲上去了,到此證實一切操做正常。

 AfxBeginThread 與 CreateThread 的區別

簡言之:  AfxBeginThread是MFC的全局函數,是對CreateThread的封裝。CreateThread是Win32 API函數,前者最終要調到後者。
1>.
具體說來,CreateThread這個 函數是windows提供給用戶的 API函數,是SDK的標準形式,在使用的過程中要考慮到進程的同步與互斥的關係,進程間的同步互斥等一系列會致使操做系統死鎖的因素,用起來比較繁瑣一些,初學的人在用到的時候可能會產生不可預料的錯誤,建議多使用AfxBeginThread,是編譯器對原來的CreateThread函數的封裝,用與MFC編程(固然,只要修改了項目屬性,console和win32項目都能調用)而_beginthread是C的運行庫函數。
2>
在使用AfxBeginThread時線程函數的定義爲:UINT   _yourThreadFun(LPVOID   pParam)參數必須如此;
在使用CreateThread時,線程的函數定義爲: DWORD WINAPI _yourThreadFun(LPVOID pParameter)

二者實質是同樣的,
不過AfxBeginThread返回CWinThread指針,就是說它會new一個CWinThread對象,而這個對象在線程運行結束時是會自動刪除的,
CreatThread,它返回的是一個句柄,若是你不使用CloseHandle的話就能夠經過它安全的瞭解線程狀態,

相關文章
相關標籤/搜索