日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

CreateThread

發(fā)布時(shí)間:2025/3/12 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CreateThread 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

CreateThread是一種微軟在Windows API中提供了建立新的線程的函數(shù),該函數(shù)在主線程的基礎(chǔ)上創(chuàng)建一個(gè)新線程。線程中止運(yùn)行后,線程對(duì)象仍然在系統(tǒng)中,必須通過(guò)CloseHandle函數(shù)來(lái)關(guān)閉該線程對(duì)象。

在很多參考書上,都說(shuō)不要用CreateThread 創(chuàng)建線程、并用CloseHandle來(lái)關(guān)閉這個(gè)線程,因?yàn)檫@樣做會(huì)導(dǎo)致內(nèi)存泄漏,而應(yīng)該用_beginthread來(lái)創(chuàng)建線程,_endthread來(lái)銷毀線程。 中文名
CreateThread
外文名
CreateThread
聲明位置
processthreadsapi.h
返回值類型
HANDLE
調(diào)用方式
__stdcall

目錄

  • 1 步驟
  • 2 函數(shù)原型
  • 3 參數(shù)說(shuō)明
  • 4 內(nèi)存泄漏
  • 5 示例
  • CreateThread步驟

    編輯 CreateThread將在主線程的基礎(chǔ)上創(chuàng)建一個(gè)新線程,大致做如下步驟: 1.在內(nèi)核對(duì)象中分配一個(gè)線程標(biāo)識(shí)/句柄,可供管理,由CreateThread返回 2.把線程退出碼置為STILL_ACTIVE,把線程掛起計(jì)數(shù)置1 3.分配context結(jié)構(gòu) 4.分配兩頁(yè)的物理存儲(chǔ)以準(zhǔn)備棧,保護(hù)頁(yè)設(shè)置為PAGE_READWRITE,第2頁(yè)設(shè)為PAGE_GUARD 5.lpStartAddr和lpvThread值被放在棧頂,使它們成為傳送給StartOfThread的參數(shù) 6.把context結(jié)構(gòu)的棧指針指向棧頂(第5步)指令指針指向startOfThread函數(shù)

    CreateThread函數(shù)原型

    編輯 MSDN中CreateThread原型: HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,//SD SIZE_T dwStackSize,//initialstacksize LPTHREAD_START_ROUTINE lpStartAddress,//threadfunction LPVOID lpParameter,//threadargument DWORD dwCreationFlags,//creationoption LPDWORD lpThreadId//threadidentifier ) processthreadsapi.h中CreateThread原型: WINBASEAPI _Ret_maybenull_ HANDLE WINAPI CreateThread( _In_opt_LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_SIZE_T dwStackSize, _In_LPTHREAD_START_ROUTINE lpStartAddress, _In_opt___drv_aliasesMemLPVOID lpParameter, _In_DWORD dwCreationFlags, _Out_opt_LPDWORD lpThreadId );

    CreateThread參數(shù)說(shuō)明

    編輯 lpThreadAttributes:指向SECURITY_ATTRIBUTES型態(tài)的結(jié)構(gòu)的指針。在Windows 98中忽略該參數(shù)。在Windows NT中,NULL使用默認(rèn)安全性,不可以被子線程繼承,否則需要定義一個(gè)結(jié)構(gòu)體將它的bInheritHandle成員初始化為TRUE dwStackSize,設(shè)置初始棧的大小,以字節(jié)為單位,如果為0,那么默認(rèn)將使用與調(diào)用該函數(shù)的線程相同的棧空間大小。任何情況下,Windows根據(jù)需要?jiǎng)討B(tài)延長(zhǎng)堆棧的大小。 lpStartAddress,指向線程函數(shù)的指針,形式:@函數(shù)名,函數(shù)名稱沒(méi)有限制,但是必須以下列形式聲明: DWORD WINAPI 函數(shù)名 (LPVOID lpParam) ,格式不正確將無(wú)法調(diào)用成功。 //也可以直接調(diào)用void類型 //但lpStartAddress要這樣通過(guò)LPTHREAD_START_ROUTINE轉(zhuǎn)換如: (LPTHREAD_START_ROUTINE)MyVoid //然后在線程聲明為: void MyVoid() { return; } lpParameter:向線程函數(shù)傳遞的參數(shù),是一個(gè)指向結(jié)構(gòu)的指針,不需傳遞參數(shù)時(shí),為NULL。 dwCreationFlags :線程標(biāo)志,可取值如下 (1)CREATE_SUSPENDED(0x00000004):創(chuàng)建一個(gè)掛起的線程, (2)0:表示創(chuàng)建后立即激活。 (3)STACK_SIZE_PARAM_IS_A_RESERVATION(0x00010000):dwStackSize參數(shù)指定初始的保留堆棧 的大小,否則,dwStackSize指定提交的大小。該標(biāo)記值在Windows 2000/NT and Windows Me/98/95上不支持。 lpThreadId:保存新線程的id。 返回值:函數(shù)成功,返回線程句柄;函數(shù)失敗返回false。若不想返回線程ID,設(shè)置值為NULL。 函數(shù)說(shuō)明: 創(chuàng)建一個(gè)線程。 語(yǔ)法: hThread = CreateThread (&security_attributes, dwStackSize, ThreadProc,pParam, dwFlags, &idThread) ; 一般并不推薦使用 CreateThread函數(shù),而推薦使用RTL庫(kù)里的System單元中定義的 BeginThread函數(shù),因?yàn)檫@除了能創(chuàng)建一個(gè)線程和一個(gè)入口函數(shù)以外,還增加了幾項(xiàng)保護(hù)措施。 在MFC程序中,應(yīng)該調(diào)用AfxBeginThread函數(shù),在Visual C++程序中應(yīng)調(diào)用_beginthreadex函數(shù)。

    CreateThread內(nèi)存泄漏

    編輯 其實(shí),真正的原因并非如此。看如下一段代碼: ?
    1 2 3 4 5 6 7 8 HANDLECreateThread( LPSECURITY_ATTRIBUTESlpThreadAttributes,//線程安全屬性 DWORDdwStackSize,//堆棧大小 LPTHREAD_START_ROUTINElpStartAddress,//線程函數(shù) LPVOIDlpParameter,//線程參數(shù) DWORDdwCreationFlags,//線程創(chuàng)建屬性 LPDWORDlpThreadId//線程ID );
    CloseHandle函數(shù)的原型是: BOOL CloseHandle( HANDLE hObject );//HANDLE hObject 對(duì)象句柄 CloseHandle可以關(guān)閉多種類型的對(duì)象,比如文件對(duì)象等,這里使用這個(gè)函數(shù)來(lái)關(guān)閉線程對(duì)象。調(diào)用時(shí),hObject為待關(guān)閉的線程對(duì)象的句柄。 說(shuō)使用這種方法可能會(huì)引發(fā)內(nèi)存泄漏問(wèn)題,其實(shí)不完全正確。那為什么會(huì)引起內(nèi)存的泄漏呢?因?yàn)楫?dāng)線程的函數(shù)用到了C的標(biāo)準(zhǔn)庫(kù)的時(shí)候,很容易導(dǎo)致沖突,所以在創(chuàng)建VC的工程時(shí),系統(tǒng)提示是用單線程還是用多線程的庫(kù),因?yàn)樵贑的內(nèi)部有很多的全局變量。例如,出錯(cuò)號(hào)、文件句柄等全局變量。 因?yàn)樵贑的庫(kù)中有全局變量,這樣用C的庫(kù)時(shí),如果程序中使用了標(biāo)準(zhǔn)的C程序庫(kù)時(shí),就很容易導(dǎo)致運(yùn)行不正常,會(huì)引起很多的沖突。所以,微軟和Borland都對(duì)C的庫(kù)進(jìn)行了一些改進(jìn)。但是這個(gè)改進(jìn)的一個(gè)條件就是,如果一個(gè)線程已經(jīng)開(kāi)始創(chuàng)建了,就應(yīng)該創(chuàng)建一個(gè)結(jié)構(gòu)來(lái)包含這些全局變量,接著把這些全局變量放入線程的上下文中和這個(gè)線程相關(guān)起來(lái)。這樣,全局變量就會(huì)依賴于這個(gè)線程,不會(huì)引起沖突。 這樣做就會(huì)有一個(gè)問(wèn)題,什么時(shí)候這個(gè)線程開(kāi)始創(chuàng)建呢?標(biāo)準(zhǔn)的Windows的API是不知道的,因?yàn)樗庆o態(tài)的庫(kù)。這些庫(kù)都是放在VC的LIB的目錄內(nèi)的,而線程函數(shù)是操作系統(tǒng)的函數(shù)。所以,VC和BC在創(chuàng)建線程時(shí),都會(huì)用_beginThread來(lái)創(chuàng)建線程,再用_endThread來(lái)結(jié)束線程。這樣,它們?cè)趧?chuàng)建線程的時(shí)候,就會(huì)知道什么時(shí)候創(chuàng)建了線程,并把全局變量放入某一結(jié)構(gòu)中,讓它和線程能關(guān)聯(lián)起來(lái)。這樣就不會(huì)發(fā)生沖突了。 很顯然,要完成這個(gè)功能,首先需要分配結(jié)構(gòu)表把全局變量包含起來(lái)。這個(gè)過(guò)程是在_beginThread時(shí)做的,而釋放則是在_endTread內(nèi)完成。 所以,當(dāng)用_beginThread來(lái)創(chuàng)建,而用CloseHandle來(lái)關(guān)閉線程時(shí),這時(shí)復(fù)制的全局結(jié)構(gòu)就不會(huì)被釋放了,這就有了內(nèi)存的泄漏。這就是很多資料所說(shuō)的內(nèi)存泄漏問(wèn)題的真正的原因。 其實(shí),可以不用_beginThread和_endThread這一對(duì)函數(shù)。如果用CreateThread函數(shù)創(chuàng)建,用CloseHandle關(guān)閉,那么,與C有關(guān)的庫(kù)就會(huì)用全局的,它們會(huì)引起沖突。所以,比較好的方法就是在線程內(nèi)不用標(biāo)準(zhǔn)的C的庫(kù)(可以使用Windows API的庫(kù)函數(shù))。這樣就不會(huì)有什么問(wèn)題,也就不會(huì)引起沖突。例如,字符串的操作函數(shù)、文件操作等。 當(dāng)某個(gè)程序創(chuàng)建一個(gè)線程后,會(huì)產(chǎn)生一個(gè)線程的句柄,線程的句柄主要用來(lái)控制整個(gè)線程的運(yùn)行,例如停止、掛起或設(shè)置線程的優(yōu)先級(jí)等操作。 (這是VC6.0的早期BUG,后來(lái)的vs版本都修復(fù)了這個(gè)漏洞。老問(wèn)題不值得重談!)

    CreateThread示例

    編輯 CreateThread 函數(shù)從一個(gè)進(jìn)程里面創(chuàng)建一個(gè)線程。這個(gè)開(kāi)始的線程必須指定開(kāi)始執(zhí)行代碼的地址,新線程執(zhí)行。有代表性的,開(kāi)始地址就是一個(gè)函數(shù)名。這個(gè)函數(shù)有一個(gè)參數(shù),并且返回一個(gè) DWORD 值。一個(gè)進(jìn)程里面同時(shí)有多個(gè)線程在執(zhí)行。 下面這個(gè)例子演示如何創(chuàng)建一個(gè)新線程,執(zhí)行本地定義的函數(shù)。 ThreadProc. 建立的線程動(dòng)態(tài)分配內(nèi)存?zhèn)鬟f信息到每個(gè)線程的實(shí)例中。線程函數(shù)負(fù)責(zé)釋放這些內(nèi)存。 被調(diào)用的線程用 WaitForMultipleObjects 持續(xù)等待,直到所有的工作線程退出。在線程退出后,關(guān)掉線程函數(shù)的句柄。 ?
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 #include?<windows.h> #include?<strsafe.h>//win2003SDK必須安裝 要不無(wú)此頭文件。此文件是為了實(shí)現(xiàn)StringCchPrintf,StringCchLength。 #define?MAX_THREADS????3 #define?BUF_SIZE????255 typedef?struct?_MyData{ int?val1; int?val2; }MYDATA,*PMYDATA; DWORD?WINAPI?ThreadProc(LPVOID?lpParam) { ????HANDLE?hStdout; ????PMYDATA?pData; ????TCHAR?msgBuf[BUF_SIZE]; ????size_tcchStringSize; ????DWORD?dwChars; ????hStdout=GetStdHandle(STD_OUTPUT_HANDLE); ????if(hStdout==INVALID_HANDLE_VALUE) ????return?1; ????//Cast?the?parameter?to?the?correct?data?type. ????pData=(PMYDATA)lpParam; ????//Print?the?parameter?values?using?thread-safe?functions. ????StringCchPrintf(msgBuf,BUF_SIZE,TEXT("Parameters=%d,%d\n"), ????pData->val1,pData->val2); ????StringCchLength(msgBuf,BUF_SIZE,&cchStringSize); ????WriteConsole(hStdout,msgBuf,cchStringSize,&dwChars,NULL); ????//Free?the?memory?allocated?by?the?caller?for?the?thread ????//data?structure. ????HeapFree(GetProcessHeap(),0,pData); ????return?0; } void?main() { ????PMYDATA?pData; ????DWORD?dwThreadId[MAX_THREADS]; ????HANDLE?hThread[MAX_THREADS]; ????int?i; ????//Create?MAX_THREADS?worker?threads. ????for(i?=?0;?i?<?MAX_THREADS;?i++) ????{ ????????//Allocate?memory?for?thread?data. ????????pData=(PMYDATA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, ????????sizeof(MYDATA)); ????????if(pData==NULL) ????????ExitProcess(2); ????????//Generate?unique?data?for?each?thread. ????????pData->val1=i; ????????pData->val2=i+100; ????????hThread[i]=CreateThread( ????????NULL,//default?security?attributes ????????0,//use?default?stack?size ????????ThreadProc,//thread?function ????????pData,//argument?to?thread?function ????????0,//use?default?creation?flags ????????&dwThreadId[i]);//returns?the?thread?identifier ????????//Check?there?turn?value?for?success. ????????if(hThread[i]==NULL) ????????{ ????????????ExitProcess(i); ????????} ????} ????//Wait?until?all?threads?have?terminated. ????WaitForMultipleObjects(MAX_THREADS,hThread,TRUE,INFINITE); ????//Close?all?thread?handle?supon?completion. ????for(i=0;i<MAX_THREADS;i++) ????{ ????????CloseHandle(hThread[i]); ????}???? }
    與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

    總結(jié)

    以上是生活随笔為你收集整理的CreateThread的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。