千家信息网

如何用_beginthreadex()创建线程

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,这篇文章主要讲解了"如何用_beginthreadex()创建线程",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何用_beginthreadex()
千家信息网最后更新 2024年09月22日如何用_beginthreadex()创建线程

这篇文章主要讲解了"如何用_beginthreadex()创建线程",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何用_beginthreadex()创建线程"吧!

一、使用_beginthreadex()

需要的头文件支持#include // for _beginthread()
需要的设置:ProjectàSetting-->C/C++-->User run-time library 选择Debug Multithreaded 或者Multithreaded。即使用: MTMTD

代码如下:

#include #include              // for STL string class#include           // for HANDLE#include           // 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 cast      pthX->ThreadEntryPoint();           // now call the true entry-point-function      return 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   hth2;    unsigned  uiThread1ID;    hth2 = (HANDLE)_beginthreadex( NULL,         // security                                   0,            // stack size                                   ThreadX::ThreadStaticEntryPoint,                                   o1,           // arg list                                   CREATE_SUSPENDED,  // so we can later call ResumeThread()                                   &uiThread1ID );    if ( hth2 == 0 )        printf("Failed to create thread 1\n");    DWORD   dwExitCode;    GetExitCodeThread( hth2, &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259    printf( "initial thread 1 exit code = %u\n", dwExitCode );    o1->threadName = "t1";    ThreadX * o2 = new ThreadX( -100000, 0, 2000 );    HANDLE   hth3;    unsigned  uiThread2ID;    hth3 = (HANDLE)_beginthreadex( NULL,         // security                                   0,            // stack size                                   ThreadX::ThreadStaticEntryPoint,                                   o2,           // arg list                                   CREATE_SUSPENDED,  // so we can later call ResumeThread()                                   &uiThread2ID );    if ( hth3 == 0 )        printf("Failed to create thread 2\n");    GetExitCodeThread( hth3, &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259    printf( "initial thread 2 exit code = %u\n", dwExitCode );    o2->threadName = "t2";    ResumeThread( hth2 );   // serves the purpose of Jaeschke's t1->Start()    ResumeThread( hth3 );       WaitForSingleObject( hth2, INFINITE );    WaitForSingleObject( hth3, INFINITE );    GetExitCodeThread( hth2, &dwExitCode );    printf( "thread 1 exited with code %u\n", dwExitCode );    GetExitCodeThread( hth3, &dwExitCode );    printf( "thread 2 exited with code %u\n", dwExitCode );    CloseHandle( hth2 );    CloseHandle( hth3 );    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那样,返回新创建的线程的句柄。

  • (4)C++主线程的终止,同时也会终止所有主线程创建的子线程,不管子线程有没有执行完毕。所以上面的代码中如果不调用WaitForSingleObject,则2个子线程t1和t2可能并没有执行完毕或根本没有执行。

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

二、_beginthreadex()与代CreateThread()区别

CreateThread是Windows的API函数(SDK函数的标准形式,直截了当的创建方式,任何场合都可以使用),提供操作系统级别的创建线程的操作,且仅限于工作者线程。不调用MFC和RTL的函数时,可以用CreateThread,其它情况不要轻易。在使用的过程中要考虑到进程的同步与互斥的关系(防止死锁)。线程函数定义为:DWORD WINAPI _yourThreadFun(LPVOID pParameter)。但它没有考虑:

  • (1)C Runtime中需要对多线程进行纪录和初始化,以保证C函数库工作正常(典型的例子是strtok函数)。

  • (2)MFC也需要知道新线程的创建,也需要做一些初始化工作(当然,如果没用MFC就没事了)。

AfxBeginThread:MFC中线程创建的MFC函数,首先创建了相应的CWinThread对象,然后调用CWinThread::CreateThread, 在CWinThread::CreateThread中,完成了对线程对象的初始化工作,然后,调用_beginthreadex(AfxBeginThread相比较更为安全)创建线程。它简化了操作或让线程能够响应消息,即可用于界面线程,也可以用于工作者线程,但要注意不要在一个MFC程序中使用_beginthreadex()或CreateThread()。线程函数定义为:UINT
_yourThreadFun(LPVOID pParam)

_beginthreadex:MS对C Runtime库的扩展SDK函数,首先针对C Runtime库做了一些初始化的工作,以保证C Runtime库工作正常。然后,调用CreateThread真正创建线程。 仅使用Runtime Library时,可以用_BegingThread。

  • 小节:实际上,这三个函数之间存在一定的调用关系,第一个纯粹一些,后两个完成自己相应的工作之后,调用前者实现线程的创建。其中CreateThread是由操作系统提供的接口,而AfxBeginThread_BeginThread则是编译器对它的封装。

  • 小节:用_beginthreadex()_endthreadex函数应该是最佳选择,且都是C Run-time Library中的函数,函数的参数和数据类型都是C Run-time Library中的类型,这样在启动线程时就不需要进行Windows数据类型和C Run-time Library中的数据类型之间的转化,从而,减低了线程启动时的资源消耗和时间的消耗。但使用_beginthread,无法创建带有安全属性的新线程,无法创建暂停的线程,也无法获得 线程ID,_endthread的情况类似,它不带参数,这意味这线程的退出代码必须硬编码为0。

  • 小节:MFC也是C++类库(只不过是Microsoft的C++类库,不是标准的C++类库),在MFC中也封装了new和delete两中运算符,所以用到new和delete的地方不一定非要使用_beginthreadex() 函数,用其他两个函数都可以。

_beginthreadex_beginthread在回调入口函数之前进行一些线程相关的CRT的初始化操作。
CRT的函数库在线程出现之前就已经存在,所以原有的CRT不能真正支持线程,
这也导致了许多CRT的函数在多线程的情况下必须有特殊的支持,不能简单的使用CreateThread就OK。

补充一点:_beginthreadex()是针对CRT的线程函数,在线程中若要用到CRT的函数,最好用这个启动线程,如果不用这个会有内存泄漏。

感谢各位的阅读,以上就是"如何用_beginthreadex()创建线程"的内容了,经过本文的学习后,相信大家对如何用_beginthreadex()创建线程这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

线程 函数 工作 类型 代码 参数 情况 数据 C++ 编译 小节 编译器 行期 死锁 学习 支持 选择 相同 安全 操作系统 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 专家解读网络安全法ppt 四川仁贤领冠互联网科技有限公司 近期国内网络安全形势 民法包括网络安全法吗 护苗网络安全防护 软件开发方案能申请专利吗 绝地求生账号申诉服务器选择 上海阿瑞思科技网络技术公司 国家网络安全电信宣传周是哪天 三级数据库技术考试怎么考 如何打开已经建立的数据库 数据库冷备份 热备份过程 长沙停车场软件开发 英雄联盟大洋洲属于哪个服务器 联软科技网络安全准入控制 千人千面的数据库 越秀网络安全服务 幻塔服务器已有角色查询 北京行业软件开发 公司软件开发外包分录 编程语言和数据库技术 养羊互联网科技平台 网络安全重要场所物理防御 艾尔登法环 无法登陆服务器 网络安全授课课件 网易我的世界开启服务器教程 会议服务器安装视频 硬件软件开发流程图 互联网科技公司的英语 京东商城商品数据库
0