建立執行緒——_beginthread 和 _beginthreadex【方法2】
阿新 • • 發佈:2018-12-18
並不是Windows標準API,建立執行緒函式,該函底層呼叫CreateThread。
標頭檔案
#include <process.h>
函式原型
unsigned long _beginthread(
void(_cdecl *start_address)(void *), //宣告為void (*start_address)(void *)形式
unsigned stack_size, //是執行緒堆疊大小,一般預設為0
void *arglist //向執行緒傳遞的引數,一般為結構體
);
typedef unsigned int uintptr_t;
typedef unsigned (__stdcall* _beginthreadex_proc_type)(void*);
uintptr_t _beginthreadex(
void* _Security, //執行緒安全屬性
unsigned _StackSize, //執行緒堆疊大小
_beginthreadex_proc_type _StartAddress, //執行緒函式地址
void* _ArgList, //傳遞給執行緒函式的地址
unsigned _InitFlag, //指定執行緒是否立即啟動
unsigned * _ThrdAddr //儲存執行緒id號
);
安全屬性
SECURITY_ATTRIBUTES結構包含一個物件的安全描述符,並指定檢索到指定這個結構的控制代碼是否是可繼承的。這個結構為很多函式建立物件時提供安全性設定。如:CreateFile,CreatePipe,CreateProcess,RegCreateKeyEx,RegSaveKeyEx。
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength; //結構體的大小,可用SIZEOF取得
LPVOID lpSecurityDescriptor; //安全描述符
BOOL bInheritHandle; //安全描述的物件能否被新建立的程序繼承
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
執行緒終止
執行緒函式退出。 執行緒使用的堆疊被釋放。 dwExitCode設定為執行緒函式的返回值。 遞減核心中的code值,讓核心的引用計數減一。
-
結束執行緒呼叫,終止自己
VOID WINAPI ExitThread( __in DWORD dwExitCode // 執行緒結束時的退出碼 );
-
由當前執行緒終止其他執行緒
BOOL WINAPI TerminateThread( __in_out HANDLE hThread, // 終止的執行緒控制代碼 __in DWORD dwExitCode // 退出碼 );
-
釋放執行緒空間、釋放執行緒TLS空間、呼叫ExiteThread結束執行緒
void _endthread(void); // retval:設定的執行緒結束碼,與ExiteThread函式的引數功能一樣, //其實這個函式釋放執行緒TLS空間,再呼叫ExiteThread函式,但沒有釋放執行緒空間。 void _endthreadex(unsigned retval);
可以顯示的呼叫這兩個函式來結束執行緒。系統從執行緒啟動函式返回時,也會自動呼叫相應的結束 執行緒函式,收回分配給執行緒的資源。
區別
兩組函式都是用來建立和結束執行緒的。這兩對函式的不同點如下:
- 從形式上開,_beginthreadex()更像CreateThread()。_beginthreadex()比_beginthread()多3個引數:intiflag,security和threadaddr。
- 兩種建立方式的執行緒函式不同。_beginthreadex()的執行緒函式必須呼叫_stdcall呼叫方式,而且必須返回一個unsigned int型的退出碼。
- _beginthreadex()在建立執行緒失敗時返回0,而_beginthread()在建立執行緒失敗時返回-1。這一點是在檢查返回結果是必須注意的。
- 如果是呼叫_beginthread()建立執行緒,並相應地呼叫_endthread()結束執行緒時,系統自動關閉執行緒控制代碼;而呼叫_beginthreadx()建立執行緒,並相應地呼叫_endthreadx()結束執行緒時,系統不能自動關閉執行緒控制代碼。因此呼叫_beginthreadx()建立執行緒還需程式設計師自己關閉執行緒控制代碼,以清除執行緒的地址空間。
例項
例項一:
#include <iostream>
#include <windows.h>
#include <process.h>
using namespace std;
unsigned int WINAPI ThreadProFunc(void *pParam);
int main(int argc, char **argv)
{
HANDLE hThread;
unsigned int threadId;
hThread = (HANDLE)_beginthreadex(NULL, NULL, ThreadProFunc, NULL, 0, &threadId);
for (int i = 0; i < 100; i++) {
cout << "nihao" << endl;
}
CloseHandle(hThread); //關閉執行緒控制代碼
system("pause");
return 0;
}
unsigned int WINAPI ThreadProFunc(void *pParam)
{
for (int i = 0; i < 100; i++) {
cout<<"hello\n";
}
return 0;
}
槍戰模式
例項二:
#include <Windows.h>
#include <process.h>
#include <iostream>
using namespace std;
typedef struct _STRUCT_DATA_
{
int id; //用於標識出票id
int tickets;
}_DATA, *_pDATA;
//CRITICAL_SECTION g_cs;
unsigned __stdcall Fun1(LPVOID lpParam);
unsigned __stdcall Fun2(LPVOID lpParam);
void main()
{
HANDLE hThread[2] = { NULL,NULL };
unsigned threadid[2] = { 0 };
_DATA stru_data;
stru_data.id = 0;
stru_data.tickets = 200;
hThread[0] = (HANDLE)_beginthreadex(NULL, 0, Fun1, &stru_data, 0, &threadid[0]);
hThread[1] = (HANDLE)_beginthreadex(NULL, 0, Fun2, &stru_data, 0, &threadid[1]);
//InitializeCriticalSection(&g_cs);
Sleep(4000);
//LeaveCriticalSection(&g_cs);
}
unsigned __stdcall Fun1(LPVOID lpParam)
{
_pDATA data = (_pDATA)lpParam;
while (TRUE)
{
//EnterCriticalSection(&g_cs);
if (data->tickets > 0)
{
Sleep(1);
cout << "fun1: " << data->id++ ;
cout << " *** thread 1 :sell ticket: " << data->tickets-- << endl;
//LeaveCriticalSection(&g_cs);
}
else
{
//LeaveCriticalSection(&g_cs);
break;
}
}
return 0;
}
unsigned __stdcall Fun2(LPVOID lpParam)
{
_pDATA data = (_pDATA)lpParam;
while (TRUE)
{
//EnterCriticalSection(&g_cs);
if (data->tickets > 0)
{
Sleep(1);
cout << "fun2: " << data->id++ ;
cout << " === thread 2:sell ticket: " << data->tickets-- << endl;
// LeaveCriticalSection(&g_cs);
}
else
{
//LeaveCriticalSection(&g_cs);
break;
}
}
return 0;
}