_beginThreadex创建多线程解读

一、须要的头文件支持

#include <process.h>         // for _beginthread()

须要的设置:ProjectàSetting-->C/C++-->User run-time library 选择Debug Multithreaded 或者Multithreaded。即使用: MT或MTD。

源代码例如以下:

#include <stdio.h>
#include <string>             // for STL string class
#include <windows.h>          // for HANDLE
#include <process.h>          // for _beginthread()
using namespace std;class ThreadX
{
private:int loopStart;int loopEnd;int dispFrequency;
public:string threadName;ThreadX( int startValue, int endValue, int frequency ){loopStart = startValue;loopEnd = endValue;dispFrequency = frequency;}static unsigned __stdcall ThreadStaticEntryPoint(void * pThis){ThreadX * pthX = (ThreadX*)pThis;   // the tricky castpthX->ThreadEntryPoint();           // now call the true entry-point-functionreturn 1;                           // the thread exit code}void ThreadEntryPoint(){for (int i = loopStart; i <= loopEnd; ++i){if (i % dispFrequency == 0){printf( "%s: i = %d\n", threadName.c_str(), i );}}printf( "%s thread terminating\n", threadName.c_str() );}
};int main()
{ThreadX * o1 = new ThreadX( 0, 1, 2000 );HANDLE   hth1;unsigned  uiThread1ID;hth1 = (HANDLE)_beginthreadex( NULL,         // security0,            // stack sizeThreadX::ThreadStaticEntryPoint,o1,           // arg listCREATE_SUSPENDED,  // so we can later call ResumeThread()&uiThread1ID );if ( hth1 == 0 )printf("Failed to create thread 1\n");DWORD   dwExitCode;GetExitCodeThread( hth1, &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259printf( "initial thread 1 exit code = %u\n", dwExitCode );o1->threadName = "t1";ThreadX * o2 = new ThreadX( -100000, 0, 2000 );HANDLE   hth2;unsigned  uiThread2ID;hth2 = (HANDLE)_beginthreadex( NULL,         // security0,            // stack sizeThreadX::ThreadStaticEntryPoint,o2,           // arg listCREATE_SUSPENDED,  // so we can later call ResumeThread()&uiThread2ID );if ( hth2 == 0 )printf("Failed to create thread 2\n");GetExitCodeThread( hth2, &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259printf( "initial thread 2 exit code = %u\n", dwExitCode );o2->threadName = "t2";ResumeThread( hth1 );   // serves the purpose of Jaeschke's t1->Start()ResumeThread( hth2 );   WaitForSingleObject( hth1, INFINITE );WaitForSingleObject( hth2, INFINITE );GetExitCodeThread( hth1, &dwExitCode );printf( "thread 1 exited with code %u\n", dwExitCode );GetExitCodeThread( hth2, &dwExitCode );printf( "thread 2 exited with code %u\n", dwExitCode );CloseHandle( hth1 );CloseHandle( hth2 );delete o1;o1 = NULL;delete o2;o2 = NULL;printf("Primary thread terminating.\n");return 0;
}

二、解释

(1)假设你正在编写C/C++代码,决不应该调用CreateThread。相反,应该使用VisualC++执行期库函数_beginthreadex,退出也应该使用_endthreadex。假设不使用Microsoft的VisualC++编译器,你的编译器供应商有它自己的CreateThread替代函数。无论这个替代函数是什么,你都必须使用。

(2)由于_beginthreadex和_endthreadex是CRT线程函数,所以必须注意编译选项runtimelibaray的选择,使用MT或MTD。[MultiThreaded , Debug MultiThreaded]。

(3)_beginthreadex函数的參数列表与CreateThread函数的參数列表是同样的,可是參数名和类型并不全然同样。这是由于Microsoft的C/C++执行期库的开发小组觉得,C/C++执行期函数不应该对Windows数据类型有不论什么依赖。_beginthreadex函数也像CreateThread那样,返回新创建的线程的句柄。

以下是关于_beginthreadex的一些要点:

1)每一个线程均获得由C/C++执行期库的堆栈分配的自己的tiddata内存结构。(tiddata结构位于Mtdll.h文件里的VisualC++源码中)。

2)传递给_beginthreadex的线程函数的地址保存在tiddata内存块中。传递给该函数的參数也保存在该数据块中。

3)_beginthreadex确实从内部调用CreateThread,由于这是操作系统了解怎样创建新线程的唯一方法。

4)当调用CreatetThread时,它被告知通过调用_threadstartex而不是pfnStartAddr来启动运行新线程。还有,传递给线程函数的參数是tiddata结构而不是pvParam的地址。

5)假设一切顺利,就会像CreateThread那样返回线程句柄。假设不论什么操作失败了,便返回NULL。

(4)_endthreadex的一些要点:

C执行期库的_getptd函数内部调用操作系统的TlsGetValue函数,该函数负责检索调用线程的tiddata内存块的地址。

然后该数据块被释放,而操作系统的ExitThread函数被调用,以便真正撤消该线程。当然,退出代码要正确地设置和传递。

(5)尽管也提供了简化版的的_beginthread和_endthread,可是可控制性太差,所以一般不使用。

(6)线程handle由于是内核对象,所以须要在最后closehandle。

(7)很多其它的API:

HANDLE GetCurrentProcess();

HANDLE GetCurrentThread();

DWORD GetCurrentProcessId();

DWORD GetCurrentThreadId()。

DWORD SetThreadIdealProcessor(HANDLE hThread,DWORDdwIdealProcessor);

BOOL SetThreadPriority(HANDLE hThread,int nPriority);

BOOL SetPriorityClass(GetCurrentProcess(),  IDLE_PRIORITY_CLASS);

BOOL GetThreadContext(HANDLE hThread,PCONTEXTpContext);

BOOL SwitchToThread();

三、注意

(1)C++主线程的终止,同一时候也会终止全部主线程创建的子线程,无论子线程有没有运行完成。所以上面的代码中假设不调用WaitForSingleObject,则2个子线程t1和t2可能并没有运行完成或根本没有运行。

(2)假设某线程挂起,然后有调用WaitForSingleObject等待该线程,就会导致死锁。所以上面的代码假设不调用resumethread,则会死锁。

四、为什么用_beginthreadex而不是CreateThread?

为什么要用C执行时库的_beginthreadex取代操作系统的CreateThread来创建线程?

来源自自1999年7月MSJ杂志的《Win32 Q&A》栏目

你或许会说我一直用CreateThread来创建线程,一直都工作得好好的,为什么要用_beginthreadex来取代CreateThread,以下让我来告诉你为什么。

回答一个问题能够有两种方式,一种是简单的,一种是复杂的。

假设你不愿意看以下的长篇大论,那我能够告诉你简单的答案:_beginthreadex在内部调用了CreateThread,在调用之前_beginthreadex做了非常多的工作,从而使得它比CreateThread更安全

转载一部分,自己总结了一部分。

_beginThreadex创建多线程解读相关推荐

  1. _beginthreadex 创建多线程解读

    一.解释 (1)如果你正在编写C/C++代码,决不应该调用CreateThread.相反,应该使用VisualC++运行期库函数_beginthreadex,退出也应该使用_endthreadex.如 ...

  2. C++多线程实例(_beginThreadex创建多线程)

    C++多线程(二)(_beginThreadex创建多线程) C/C++ Runtime 多线程函数 一 简单实例(来自codeprojct:http://www.codeproject.com/us ...

  3. _beginthreadex创建多线程的用法

    一.实例 #include <stdio.h> #include <string> // for STL string class #include <windows.h ...

  4. 采用_beginthread/_beginthreadex函数创建多线程

    1.CRT简介: CRT: (C Runtime Library)即C运行时库,是系统运行的基础,包含了c常用的函数集(如:printf,malloc,strcpy等),为运行main做了初始化环境变 ...

  5. 转:MFC中创建多线程

    MFC中创建多线程 MFC的多线程函数必须声明为静态的或者是全局函数(不同的在于全局函数不能访问类的私有静态成员,而静态类函数可以):但这样的线程函数只能访问静态的成员变量,要实现访问类的其他成员,可 ...

  6. java多线程w3c_Java创建多线程的三种方式

    前言 这篇文章主要讲述线程的概念.组成.Java创建多线程的三种方式以及线程的类型. 线程概念 线程和进程的区别 **进程:**正在运行的程序,例如:你打开 的qq音乐.exe程序,其由PCB(进程控 ...

  7. python3创建多线程的几种方法

    python3创建多线程主要有下面两种方法:函数.类 1.函数创建多线程 python3中,提供了一个内置模块threading.Thread,可以很方便的创建多线程,threading.Thread ...

  8. java 创建多线程_Java创建多线程

    Java创建多线程 下一节> 到目前为止,我们仅用到两个线程:主线程和一个子线程.然而,你的程序可以创建所需的更多线程.例如,下面的程序创建了三个子线程: // Create multiple ...

  9. 多线程初探:三种方式创建多线程详细示例

    多线程即在同一时间,可以做多件事情. 创建多线程有3种方式,分别是继承线程类,实现Runnable接口,匿名类 一:线程概念 首先要理解进程(Processor)和线程(Thread)的区别 进程:启 ...

最新文章

  1. 快速入门cocos2d-x jsbinding
  2. JBoss Modules – Module name
  3. jquery 总结
  4. centos6.8安装php7.3,CentOS7.6源码编译安装PHP 7.3.8
  5. COCI CONTEST #3 29.11.2014 KAMIONI
  6. php编写六十甲子纳音表_六十甲子纳音表详细说明,看看你属于什么命,属于那个颜色...
  7. (王道408考研操作系统)第一章计算机系统概述-第一节2:操作系统的发展史
  8. 基于FPGA实现压缩算法
  9. mysql分析函数的实现
  10. python基础代码大全-Python网络爬虫实战项目代码大全(长期更新,欢迎补充)
  11. 分享个短视频竞品分析报告
  12. mysql webmail ubuntu12.04 imap_如何在Ubuntu 18.04 LTS上安装最新的Roundcube Webmail
  13. Buildroot笔记
  14. 逃跑h5小游戏源码熊出没手机游戏
  15. 虚拟软盘启动OS方法
  16. 通用验证码识别SDK免费开源
  17. 【PPT】PPT设计丨1.实用功能丨
  18. 继承 封装 多态 (基础)描述性理解
  19. Jsdelivr CDN 加速服务又被 DNS 污染了(附临时解决方案)
  20. threeJS中4*4矩阵实现平移和旋转的原理

热门文章

  1. 父与子python下载不了_【求助】看父与子学习Python,里面有一个滑雪小游戏,加载不出图...
  2. 计算机专业课如何阅卷,全国计算机等级考试评卷老师是如何阅卷的?
  3. 使用BigDecimal时,报NumberFormatException
  4. 证书到期了_您的PMP证书到期了吗?
  5. 云主机安mysql_如何在云服务器 ECS 安装 MySQL
  6. c语言按照字节读取任何文件,【文件操作】【按字节读取】求鉴定问题……
  7. 计算机考研 东华大学,东华大学(专业学位)计算机技术考研难吗
  8. MyBatis foreach语句批量插入数据
  9. jenkins java jar_Jenkins 安装和配置、启动jar包
  10. 系统学习NLP(五)--句法分析