Windows 核心編程之6 線程核心對象

來源:互聯網
上載者:User
線程核心對象每個進程裡,都有一個線程,作業系統用線程核心對象來管理線程。線程有2部分組成:1 線程核心對象。 作業系統來管理線程   2 線程棧, 來存在函數和局部變數的地址空間。什麼情況下使用多線程?     當各個任務彼此獨立時,可以使用多線程,如:開一個後台線程來檢測文法。什麼情況下不要使用多線程?      任務聯絡緊密。如 掃描一個目錄的檔案,就不適合開多個線程處理,這樣處理起來複雜度很高!實現CreateThread 來建立一個線程.如果是C、C++代碼的話,使用_beginThreadEx來建立線程為什嗎? 因為有些C函數裡面使用了靜態變數,那麼多個線程執行的話,會有衝突,但是_beginThreadex做了線程局部處理,它內部就調用了CreateThread函數。WINBASEAPI   表示是winbase.h的API
__out_opt       表示是輸出
HANDLE
WINAPI
CreateThread(
    __in_opt  LPSECURITY_ATTRIBUTES lpThreadAttributes,   安全屬性,一般為NULL表示預設
    __in      SIZE_T dwStackSize,    線程棧的空間,一般使用0來表示預設值
    __in      LPTHREAD_START_ROUTINE lpStartAddress,  線程函數地址
    __in_opt  LPVOID lpParameter, 線程函數參數
    __in      DWORD dwCreationFlags,  建立線程時,指定啥標誌 0 表示立即開始執行,CREATE_SUSPENDED 表示暫停
    __out_opt LPDWORD lpThreadId   返回線程ID,不需要時,可以傳遞NULL,表示不關心
    );終止運行線程的4種方式:1 線程函數返回(推薦)可以清理C++對象資源,會調用C++的解構函式清理線程棧2 自己調用ExitThread(避免使用)不會調用C++的解構函式清理線程棧如果使用的是C++代碼,那麼調用_endThreadEx() 來替換ExitThread3 其它線程調用TerminateThread()  避免使用不會調用C++解構函式,也不會清理線程棧ExitThread來結束的線程,會清理堆棧,但是調用terminateThread()函數 不會清理堆棧資訊,除非線程所在進程終止。4 線程所在的進程終止                      避免使用C++解構函式不會調用,線程被強行殺死,正常的清理工作沒有執行。線程終止時,會發生以下事情:1  線程擁有的所有物件控點被釋放一個線程有2個使用者物件: 視窗和掛鈎2 退出碼有STILL_ACTIVE 變成 ExitThread 或者TerminateThread 返回的退出碼3 線程核心對象變成觸發狀態4 如果線程是最後一個活動線程,那麼進程也終止。5 線程核心對象的引用計數減一C和C++庫標準的C和C++庫,最開始不是為了多線程設計的,在多線程環境下有些函數會出問題:errno,_doserrno, strtok, _wcstok, strerror, _strerror, tmpnam, tmpfile,asctime,gmtime,等所以要不要調用系統的CreateThread,而要調用C,C++運行庫 _beginthreadex_beginthreadex 分配和初始化 初始化資料區塊,並將它與新的線程關聯起來_endthreadex  函數 線上程終止啟動並執行 釋放分配的資料區塊不要使用C和C++運行庫的這一對函數_beginthread ,
_endthread瞭解自己的身份返回當前進程的控制代碼  和  IDHANDLE GetCurrentProcess();DWORD GetCurentProceddID();返回當前線程的控制代碼   和 IDHANDLE GetCurrentThread();DWORD  GetCureentThreadID();注意: 上面這2個函數返回的都是偽控制代碼偽控制代碼:表示當前線程的控制代碼,即調用線程的控制代碼。下面舉一個樣本來分析
#include <iostream>#include <vector>#include <map>#include <Windows.h>#include <tchar.h>#include <process.h>#include <Strsafe.h>HANDLE ghthreadCurrent = NULL;unsigned int WINAPI ThreadFunc2(LPVOID lp);unsigned int WINAPI ThreadFunc1(LPVOID lp){HANDLE hThread = GetCurrentThread();ghthreadCurrent =(HANDLE) _beginthreadex(NULL, 0, ThreadFunc2, hThread, 0, NULL);while(1){printf("111\n");Sleep(1000);}return 0;}unsigned int WINAPI ThreadFunc2(LPVOID lp){HANDLE hThread = (HANDLE)lp;TerminateThread(hThread,0);return 0;}int main(){HANDLE hThread1 =(HANDLE) _beginthreadex(NULL, 0, ThreadFunc1, NULL, 0, NULL );WaitForSingleObject(hThread1,INFINITE);return 0;}
線程2 的線程函數 TerminateThread 會把自己殺死,不會殺死線程1使用一個複製控制代碼的函數 DuplicateHandle() 來複製控制代碼
#include <iostream>#include <vector>#include <map>#include <Windows.h>#include <tchar.h>#include <process.h>#include <Strsafe.h>unsigned int WINAPI ThreadFunc2(LPVOID lp);unsigned int WINAPI ThreadFunc1(LPVOID lp){HANDLE hThread = GetCurrentThread();HANDLE hTagrealThread = NULL;BOOL bOk = DuplicateHandle(GetCurrentProcess(),hThread,GetCurrentProcess(),&hTagrealThread,0,FALSE,DUPLICATE_SAME_ACCESS);(HANDLE) _beginthreadex(NULL, 0, ThreadFunc2, hTagrealThread, 0, NULL);while(1){printf("111\n");Sleep(1000);}return 0;}unsigned int WINAPI ThreadFunc2(LPVOID lp){HANDLE hThread = (HANDLE)lp;Sleep(5000);TerminateThread(hThread,0);//必須要關閉控制代碼CloseHandle(hThread);return 0;}int main(){HANDLE hThread1 =(HANDLE) _beginthreadex(NULL, 0, ThreadFunc1, NULL, 0, NULL );WaitForSingleObject(hThread1,INFINITE);CloseHandle(hThread1);printf("main exit\n");system("pause");return 0;}

線程2函數,殺死的是線程1 最後要關閉線程1的線程核心對象

複製一個控制代碼後,線程核心對象引用計數會加1

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.