1 语法
uintptr_t _beginthreadex( // NATIVE CODE
void *security,
unsigned stack_size,
unsigned ( __stdcall *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
2 参数
- security:指向security attributes结构的指针,此结构确定返回的句柄是否由子进程继承。如果security为NULL,则不能继承句柄。
- stack_size:新线程的堆栈大小或0。
- start_address:启动开始执行新线程的例程的地址。对于_beginthread,调用约定是__cdecl(针对本机代码)或__clrcall(针对托管代码);对于_beginthreadex,它是__stdcall(针对本机代码)或__clrcall(针对托管代码)。
- arglist:要传递到新线程的参数或列表或NULL。
- initflag:控制新线程的初始状态的标志。将 initflag设置为 0以立即运行,或设置为 CREATE_SUSPENDED以在挂起状态下创建线程;使用 ResumeThread 来执行此线程。将 initflag设置为 STACK_SIZE_PARAM_IS_A_RESERVATION标志以将 stack_size用作堆栈的初始保留大小(以字节计);如果未指定此标志,stack_size将指定提交大小。
- thrdaddr:指向接收线程标识符的32位变量。如果此变量为NULL,则不可用。
3 返回值
如果成功,则这些函数中的每一个都会返回一个句柄到新创建的线程;但是,如果新创建的线程退出过快,则_beginthread 可能不会返回有效句柄。
4 使用实例
unsigned int nThreadID = 0;
m_hGetOneFrameHandle[i] = (void*) _beginthreadex( NULL , 0 , WorkThread , this, 0 , &nThreadID );
if (NULL == m_hGetOneFrameHandle[i])
{
ShowErrorMsg(TEXT("Create thread fail"), 0);
}
// ch:工作线程 | en:Working thread
unsigned int __stdcall WorkThread(void* pUser)
{
if (NULL == pUser)
{
return -1;
}
CMultipleCameraDlg* pCam = (CMultipleCameraDlg*)pUser;
if (NULL == pCam)
{
return -1;
}
int nUsingCameraNum = pCam->m_nUsingCameraNum;
pCam->m_nUsingCameraNum = -1;
pCam->ThreadFun(nUsingCameraNum);
return 0;
}
注意:
- 在 Win32 API 中,创建线程的基本函数是 CreateThread,而 _beginthread(ex) 是 C++ 运行库的函数。为什么要有两个呢?因为C++ 运行库里面有一些函数使用了全局量,如果使用 CreateThread 的情况下使用这些C++ 运行库的函数,就会出现不安全的问题。而 _beginthreadex 为这些全局变量做了处理,使得每个线程都有一份独立的“全局”量。
- 所以,如果你的编程只调用 Win32 API/SDK ,就放心用 CreateThread;如果要用到
C++ 运行时间库,那么就要使用 _beginthreadex ,并且需要在编译环境中选择 Use
MultiThread Lib/DLL。- 线程handle因为是内核对象,所以需要在最后closehandle。
QT多线程
- QThread最终还是调用_beginthreadex或者CreateThread。
参考:
1、https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/beginthread-beginthreadex?view=msvc-160
2、https://www.cnblogs.com/MCSFX/p/13180726.html
网友评论