溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何用_beginthreadex()創(chuàng)建線程

發(fā)布時(shí)間:2022-01-04 17:11:25 來(lái)源:億速云 閱讀:113 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要講解了“如何用_beginthreadex()創(chuàng)建線程”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“如何用_beginthreadex()創(chuàng)建線程”吧!

一、使用_beginthreadex()             

需要的頭文件支持#include         // for _beginthread()
需要的設(shè)置:ProjectàSetting-->C/C++-->User run-time library 選擇Debug Multithreaded 或者Multithreaded。即使用: MTMTD。

代碼如下:     
 

#include <stdio.h>
#include <string>             // for STL string class
#include <windows.h>          // for HANDLE
#include <process.h>          // for _beginthread()
using namespace std;

class ThreadX
{
private:
  int loopStart;
  int loopEnd;
  int dispFrequency;
public:
  string threadName;

  ThreadX( int startValue, int endValue, int frequency )
  {
    loopStart = startValue;
    loopEnd = endValue;
    dispFrequency = frequency;
  }

  static unsigned __stdcall ThreadStaticEntryPoint(void * pThis)
  {
      ThreadX * pthX = (ThreadX*)pThis;   // the tricky cast
      pthX->ThreadEntryPoint();           // now call the true entry-point-function
      return 1;                              // the thread exit code
  }

  void ThreadEntryPoint()
  {
    for (int i = loopStart; i <= loopEnd; ++i)
    {
      if (i % dispFrequency == 0)
      {
          printf( "%s: i = %d\n", threadName.c_str(), i );
      }
    }
    printf( "%s thread terminating\n", threadName.c_str() );
  }
};


int main()
{
    ThreadX * o1 = new ThreadX( 0, 1, 2000 );

    HANDLE   hth2;
    unsigned  uiThread1ID;

    hth2 = (HANDLE)_beginthreadex( NULL,         // security
                                   0,            // stack size
                                   ThreadX::ThreadStaticEntryPoint,
                                   o1,           // arg list
                                   CREATE_SUSPENDED,  // so we can later call ResumeThread()
                                   &uiThread1ID );

    if ( hth2 == 0 )
        printf("Failed to create thread 1\n");

    DWORD   dwExitCode;
    GetExitCodeThread( hth2, &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259
    printf( "initial thread 1 exit code = %u\n", dwExitCode );

    o1->threadName = "t1";

    ThreadX * o2 = new ThreadX( -100000, 0, 2000 );

    HANDLE   hth3;
    unsigned  uiThread2ID;

    hth3 = (HANDLE)_beginthreadex( NULL,         // security
                                   0,            // stack size
                                   ThreadX::ThreadStaticEntryPoint,
                                   o2,           // arg list
                                   CREATE_SUSPENDED,  // so we can later call ResumeThread()
                                   &uiThread2ID );

    if ( hth3 == 0 )
        printf("Failed to create thread 2\n");

    GetExitCodeThread( hth3, &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259
    printf( "initial thread 2 exit code = %u\n", dwExitCode );

    o2->threadName = "t2";

    ResumeThread( hth2 );   // serves the purpose of Jaeschke's t1->Start()
    ResumeThread( hth3 );   

    WaitForSingleObject( hth2, INFINITE );
    WaitForSingleObject( hth3, INFINITE );

    GetExitCodeThread( hth2, &dwExitCode );
    printf( "thread 1 exited with code %u\n", dwExitCode );

    GetExitCodeThread( hth3, &dwExitCode );
    printf( "thread 2 exited with code %u\n", dwExitCode );

    CloseHandle( hth2 );
    CloseHandle( hth3 );

    delete o1;
    o1 = NULL;

    delete o2;
    o2 = NULL;

    printf("Primary thread terminating.\n");
    return 0;
}

注意:

  • (1)如果你正在編寫(xiě)C/C++代碼,決不應(yīng)該調(diào)用CreateThread。相反,應(yīng)該使用VisualC++運(yùn)行期庫(kù)函數(shù)_beginthreadex,退出也應(yīng)該使用_endthreadex。如果不使用Microsoft的VisualC++編譯器,你的編譯器供應(yīng)商有它自己的CreateThread替代函數(shù)。不管這個(gè)替代函數(shù)是什么,你都必須使用。

  • (2)因?yàn)?code>_beginthreadex和_endthreadex是CRT線程函數(shù),所以必須注意編譯選項(xiàng)runtimelibaray的選擇,使用MT或MTD。[MultiThreaded , Debug MultiThreaded]。

  • (3)_beginthreadex函數(shù)的參數(shù)列表與CreateThread函數(shù)的參數(shù)列表是相同的,但是參數(shù)名和類型并不完全相同。這是因?yàn)镸icrosoft的C/C++運(yùn)行期庫(kù)的開(kāi)發(fā)小組認(rèn)為,C/C++運(yùn)行期函數(shù)不應(yīng)該對(duì)Windows數(shù)據(jù)類型有任何依賴。_beginthreadex函數(shù)也像CreateThread那樣,返回新創(chuàng)建的線程的句柄。

  • (4)C++主線程的終止,同時(shí)也會(huì)終止所有主線程創(chuàng)建的子線程,不管子線程有沒(méi)有執(zhí)行完畢。所以上面的代碼中如果不調(diào)用WaitForSingleObject,則2個(gè)子線程t1和t2可能并沒(méi)有執(zhí)行完畢或根本沒(méi)有執(zhí)行。

  • (5)如果某線程掛起,然后有調(diào)用WaitForSingleObject等待該線程,就會(huì)導(dǎo)致死鎖。所以上面的代碼如果不調(diào)用resumethread,則會(huì)死鎖。

二、_beginthreadex()與代CreateThread()區(qū)別                                   

CreateThread是Windows的API函數(shù)(SDK函數(shù)的標(biāo)準(zhǔn)形式,直截了當(dāng)?shù)膭?chuàng)建方式,任何場(chǎng)合都可以使用),提供操作系統(tǒng)級(jí)別的創(chuàng)建線程的操作,且僅限于工作者線程。不調(diào)用MFC和RTL的函數(shù)時(shí),可以用CreateThread,其它情況不要輕易。在使用的過(guò)程中要考慮到進(jìn)程的同步與互斥的關(guān)系(防止死鎖)。線程函數(shù)定義為:DWORD WINAPI _yourThreadFun(LPVOID pParameter)。但它沒(méi)有考慮:

  • (1)C Runtime中需要對(duì)多線程進(jìn)行紀(jì)錄和初始化,以保證C函數(shù)庫(kù)工作正常(典型的例子是strtok函數(shù))。

  • (2)MFC也需要知道新線程的創(chuàng)建,也需要做一些初始化工作(當(dāng)然,如果沒(méi)用MFC就沒(méi)事了)。  

AfxBeginThread:MFC中線程創(chuàng)建的MFC函數(shù),首先創(chuàng)建了相應(yīng)的CWinThread對(duì)象,然后調(diào)用CWinThread::CreateThread,   在CWinThread::CreateThread中,完成了對(duì)線程對(duì)象的初始化工作,然后,調(diào)用_beginthreadex(AfxBeginThread相比較更為安全)創(chuàng)建線程。它簡(jiǎn)化了操作或讓線程能夠響應(yīng)消息,即可用于界面線程,也可以用于工作者線程,但要注意不要在一個(gè)MFC程序中使用_beginthreadex()或CreateThread()。線程函數(shù)定義為:UINT
_yourThreadFun(LPVOID pParam)

_beginthreadex:MS對(duì)C Runtime庫(kù)的擴(kuò)展SDK函數(shù),首先針對(duì)C Runtime庫(kù)做了一些初始化的工作,以保證C Runtime庫(kù)工作正常。然后,調(diào)用CreateThread真正創(chuàng)建線程。 僅使用Runtime Library時(shí),可以用_BegingThread。

  • 小節(jié):實(shí)際上,這三個(gè)函數(shù)之間存在一定的調(diào)用關(guān)系,第一個(gè)純粹一些,后兩個(gè)完成自己相應(yīng)的工作之后,調(diào)用前者實(shí)現(xiàn)線程的創(chuàng)建。其中CreateThread是由操作系統(tǒng)提供的接口,而AfxBeginThread_BeginThread則是編譯器對(duì)它的封裝。

  • 小節(jié):用_beginthreadex()、_endthreadex函數(shù)應(yīng)該是最佳選擇,且都是C Run-time Library中的函數(shù),函數(shù)的參數(shù)和數(shù)據(jù)類型都是C Run-time Library中的類型,這樣在啟動(dòng)線程時(shí)就不需要進(jìn)行Windows數(shù)據(jù)類型和C Run-time Library中的數(shù)據(jù)類型之間的轉(zhuǎn)化,從而,減低了線程啟動(dòng)時(shí)的資源消耗和時(shí)間的消耗。但使用_beginthread,無(wú)法創(chuàng)建帶有安全屬性的新線程,無(wú)法創(chuàng)建暫停的線程,也無(wú)法獲得 線程ID,_endthread的情況類似,它不帶參數(shù),這意味這線程的退出代碼必須硬編碼為0。

  • 小節(jié):MFC也是C++類庫(kù)(只不過(guò)是Microsoft的C++類庫(kù),不是標(biāo)準(zhǔn)的C++類庫(kù)),在MFC中也封裝了new和delete兩中運(yùn)算符,所以用到new和delete的地方不一定非要使用_beginthreadex() 函數(shù),用其他兩個(gè)函數(shù)都可以。

_beginthreadex_beginthread在回調(diào)入口函數(shù)之前進(jìn)行一些線程相關(guān)的CRT的初始化操作。
CRT的函數(shù)庫(kù)在線程出現(xiàn)之前就已經(jīng)存在,所以原有的CRT不能真正支持線程,
這也導(dǎo)致了許多CRT的函數(shù)在多線程的情況下必須有特殊的支持,不能簡(jiǎn)單的使用CreateThread就OK。
 

補(bǔ)充一點(diǎn):_beginthreadex()是針對(duì)CRT的線程函數(shù),在線程中若要用到CRT的函數(shù),最好用這個(gè)啟動(dòng)線程,如果不用這個(gè)會(huì)有內(nèi)存泄漏。

感謝各位的閱讀,以上就是“如何用_beginthreadex()創(chuàng)建線程”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)如何用_beginthreadex()創(chuàng)建線程這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI