決不應該呼叫CreateThread

2021-06-07 14:51:01 字數 3358 閱讀 9016

在寫c++**時,一直牢記著一句話:決不應該呼叫createthread。相反,應該使用visual   c++執行期庫函式_beginthreadex。

好像createthread函式就是老虎,既然這樣為什麼微軟要開發這個函式呢?

從網上找到的相關資料,現在彙總一下,在此對相關人員進行感謝!

摘自《windows   核心程式設計》:   

createthread函式是用來建立執行緒的windows函式。不過,如果你正在編寫c/c++**,決不應該呼叫createthread。相反,應該使用visual   c++執行期庫函式_beginthreadex。如果不使用microsoft的visual   c++編譯器,你的編譯器**商有它自己的createthred替代函式。   

若要使多執行緒c和c++程式能夠正確地執行,必須建立乙個資料結構,並將它與使用c/c++執行期庫函式的每個執行緒關聯起來。當你呼叫c/c++執行期庫時,這些函式必須知道檢視呼叫執行緒的資料塊,這樣就不會對別的執行緒產生不良影響。   

1.每個執行緒均獲得由c/c++執行期庫的堆疊分配的自己的tiddata記憶體結構。   

2.傳遞給_beginthreadex的執行緒函式的位址儲存在tiddata記憶體塊中。傳遞給該函式的引數也儲存在該資料塊中。   

3._beginthreadex確實從內部呼叫createthread,因為這是作業系統了解如何建立新執行緒的唯一方法。   

4.當呼叫createtthread時,它被告知通過呼叫_threadstartex而不是pfnstartaddr來啟動執行新執行緒。      還有,傳遞給執行緒函式的引數是tiddata結構而不是pvparam的位址。   

5.如果一切順利,就會像createthread那樣返回執行緒控制代碼。如果任何操作失敗了,便返回 null。  

_beginthreadex和_beginthread函式的區別。_beginthread函式的引數比較少,因此比特性全面的_beginthreadex函式受到更大的限制。   

例如,如果使用_beginthread,就無法建立帶有安全屬性的新執行緒,無法建立暫停的執行緒,也 無法獲得執行緒的id值。

下面摘錄csdn中的holly()的帖子進行解釋,再次表示感謝。

[url]

holly():

oldworm提供了很好的使用的例子,而且也運用了編譯控制!   

我來解釋一下理論上的區別:   

createthread、_beginthread和_beginthreadex都是用來啟動執行緒的,但大家看到oldworm沒有提供_beginthread的方式,原因簡單,_beginthread是_beginthreadex的功能子集,雖然_beginthread內部是呼叫_beginthreadex但他遮蔽了象安全特性這樣的功能,所以_beginthread與createthread不是同等級別,_beginthreadex和createthread在功能上完全可替代,我們就來比較一下_beginthreadex與createthread!   

libraries   

libc.lib   single   thread   static   library,   retail   version     

libcmt.lib   multithread   static   library,   retail   version     

msvcrt.lib   import   library   for   msvcrt.dll,   retail   version     

這樣的提示!   

對於執行緒的支援是後來的事!   

這也導致了許多crt的函式在多執行緒的情況下必須有特殊的支援,不能簡單的使用createthread就ok。   

大多的crt函式都可以在createthread執行緒中使用,看資料說只有signal()函式不可以,會導致程序終止!但可以用並不是說沒有問題!  

_beginthreadex(內部也呼叫createthread)和_endthreadex就對這個記憶體塊做了處理,所以沒有問題!(不會有人故意用createthread建立然後用_endthreadex終止吧,而且執行緒的終止最好不要顯式的呼叫終止函式,自然退出最好!)   

談到handle的問題,_beginthread的對應函式_endthread自動的呼叫了closehandle,而_beginthreadex的對應函式_endthreadex則沒有,所以closehandle無論如何都是要呼叫的不過_endthread可以幫你執行自己不必寫,其他兩種就需要自己寫!(jeffrey   richter強烈推薦盡量不用顯式的終止函式,用自然退出的方式,自然退出當然就一定要自己寫closehandle)

觀眾看點:

為何要用_beginthreadex()而非createthread?

當你打算實現乙個多執行緒(非mfc)程式,你會選擇乙個單執行緒的crt(c執行時庫)嗎?如果你的回答是no, 那麼會帶來另外乙個問題,你選擇了createthread來建立乙個執行緒嗎? 大多數人也許會立刻回答yes。可是很不幸,這是錯誤的選擇。

我先來說一下我的結論,待會告訴你為什麼。

如果要作多執行緒(非mfc)程式,在主線程以外的任何執行緒內

- 使用malloc(),free(),new

- 呼叫stdio.h或io.h,包括fopen(),open(),getchar(),write(),printf(),errno

- 使用浮點變數和浮點運算函式

- 呼叫那些使用靜態緩衝區的函式如: asctime(),strtok(),rand()等。

你就應該使用多執行緒的crt並配合_beginthreadex(該函式只存在於多執行緒crt), 其他情況下你可以使用單執行緒的crt並配合createthread。

因為對產生的執行緒而言,_beginthreadex比之createthread會為上述操作多做額外的簿記工作,比如幫助strtok()為每個執行緒準備乙份緩衝區。

然而多執行緒程式極少情況不使用上述那些函式(比如記憶體分配或者io),所以與其每次都要思考是要使用_beginthreadex還是createthread,不如就一棍子敲定_beginthreadex。

當然你也許會借助win32來處理記憶體分配和io,這時候你確實可以以單執行緒crt配合createthread,因為io的重任已經從crt轉交給了win32。這時通常你應該使用heapalloc,heapfree來處理記憶體分配,用createfile或者getstdhandle來處理io。

還有一點比較重要的是_beginthreadex傳回的雖然是個unsigned long,其實是個執行緒handle(事實上_beginthreadex在內部就是呼叫了createthread),所以你應該用closehandle來結束他。千萬不要使用exitthread()來退出_beginthreadex建立的執行緒,那樣會喪失釋放簿記資料的機會,應該使用_endthreadex.

不應該,不應該

不應該在晚上喝一整瓶利咽的搞的反胃 不應該在吃大快活的時候點一杯奶茶的 不應該一天大腦都這麼緊張 有什麼辦法,都是自己找的 在天津累,天天加班。回到廣州上兩天班更累,連睡個覺6小時都保證不了。發現現在很容易失眠,因為大腦想事情太多了,又回到了n年前在大學又做專案又參加比賽的時候了。問題是以前我睡不著...

不應該罵騰訊

我們應該鼓勵創新這是沒有任何錯誤的。但是創新是乙個連貫的過程,不是說你靈光一現想出來個東西就是創新。目前,你不但需要提出你的新想法和技術,還要馬上確確實實的實現,而且還要實現的很好!競爭是推動社會發展的很重要的因素,社會不應該允許拿著所謂的創新想法而不去好好實現的行為,因為所有的想法不能很好的服務於...

為什麼建構函式和析構函式中不應該呼叫虛函式

在語法上,構造函式呼叫虛函式當然是沒有問題的。但是這種用法不一定能得到想要的結果,還會引發一些小問題。class base virtual void func1 virtual void func2 class derived public base virtual void func1 virtu...