_beginthreadex、CreateThread、AfxBeginThread

来源:互联网 发布:巨人网络薪资 编辑:程序博客网 时间:2024/03/29 01:22

http://www.cppblog.com/totti1006/archive/2007/10/18/34539.aspx

具体说来,CreateThread这个 函数是windows提供给用户的 API函数,是SDK的标准形式,在使用的过程中要考虑到进程的同步与互斥的关系,进程间的同步互斥等一系列会导致操作系统死锁的因素,用起来比较繁琐一些,初学的人在用到的时候可能会产生不可预料的错误,建议多使用AfxBeginThread,是编译器对原来的CreateThread函数的封装,用与MFC编程(当然,只要修改了项目属性,console和win32项目都能调用)而_beginthread是C的运行库函数。                在使用AfxBeginThread时,线程函数的定义为:UINT   _yourThreadFun(LPVOID   pParam)参数必须如此                在使用CreateThread时,线程的函数定义为:  DWORD  WINAPI  _yourThreadFun(LPVOID pParameter)。
        两个的实质都是一样的,不过AfxBeginThread返回一个CWinThread的指针,就是说他会new一个CWinThread对象,而且这个对象是自动删除的(在线程运行结束时),给我们带来的不便就是无法获得它的状态,因为随时都有可能这个指针指向的是一个已经无效的内存区域,所以使用时(如果需要了解它的运行状况的话)首先CREATE_SUSPENDED让他挂起,然后m_bAutoDelete=FALSE,接着才ResumeThread,最后不要了delete那个指针。     CreatThread就方便多了,它返回的是一个句柄,如果你不使用CloseHandle的话就可以通过他安全的了解线程状态,最后不要的时候CloseHandle,Windows才会释放资源,所以我一般使用CreatThread,方便。

如果用MFC编程,不要用CreateThread,如果只是使用Runtime Library,用_BegingThread,总之,不要轻易使用CreateThread。这是因为在MFC和RTL中的函数有可能会用到些它们所封装的公用变量,也就是说AfxBeginThread和_BeginThread都有自己的启动代码是CreateThread所没有的。在用CreateThread所创建的线程中使用MFC的类和RTL函数就有可能出现问题。如果你是用汇编编写win32程序并且在线程函数中也不调用MFC和RTL的函数,那用CreateThread就没问题,或者你虽然是用C写线程函数,但你很小心没调用RTL函数也不会有问题。

  CreateThread是由操作系统提供的接口,而AfxBeginThread和_BeginThread则是编译器对它的封装。

  在可能的情况下,不要调用_beginthread,而应该调用_beginthreadex。以及对应的_endthreadex。这都是C++运行期函数。但是使用_beginthread,无法创建带有安全属性的新线程,无法创建暂停的线程,也无法获得线程ID,_endthread的情况类似,它不带参数,


结束线程的两种方式
     当你在后台用线程来打印一些图形时.有时在打印一部分后,你希望可以停下来,那么此如何让线程停止呢.下

面会详细的向你解释要结束线程的两种方式
     1 : 这是最简单的方式,也就是让线程函数执行完成,此时线程正常结束.它会返回一个值,一般0是成功结束,

当然你可以定义自己的认为合适的值来代表线程成功执行.在线程内调用AfxEndThread将会直接结束线程,此时线

程的一切资源都会被回收.
     2 : 如果你想让别一个线程B来结束线程A,那么,你就需要在这两个线程中传递信息.
不管是工作者线程还是界面线程,如果你想在线程结束后得到它的确结果,那么你可以调用
::GetExitCodeThread函数

 


  这意味这线程的退出代码必须硬编码为0。这两个函数在_beginthreadex和_endthreadex中进行调用。CreateThread不要进行直接调用。 




 

 

http://www.cnblogs.com/chuncn/archive/2009/03/08/1406096.html

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。




 

 

问题如下: 
1:《Win32多线程程序设计》第219页中间:不要在一个MFC程序中使用_beginthreadex()或CreateThread()。 
      我的程序中使用的CString/CArray等MFC类,是否我只能使用AfxBeginThread()? 

2:我的程序使用了一个库,里面用到了很多memcpy/memmove/fopen/fread等函数。 
      这些函数应该算是C   Run-time   Library中的函数吧? 
      我创建的线程中调用了这个库中的函数,是不是使用_beginthreadex()才是安全的? 

3:《Win32多线程程序设计》第228页中间:如果主线程以为的任何线程进行了以下操作,你就应该使用多线程版的C   runtime   library,并使用_beginthreadex()和_endthreadex():在C++程序中使用了new和delete。 
      我的问题是,在C++程序中,几乎都要用到new和delete,难道只有使用_beginthreadex()吗?


1、不要在一个MFC程序中使用_beginthreadex()或CreateThread()。 
这句话的意思是由于AfxBeginThread()是MFC封装的启动线程的函数,里面包含了很多和MFC相关的启动信息,而且封装了一些常用的操作,使用起来也比较简便。而用另外两个函数就需要程序员对类型,安全性检查进行更多的思考!
2、用_beginthreadex()函数应该是最佳选择,因为_beginthreadex()函数是C   Run-time   Library   中的函数,函数的参数和数据类型都是C   Run-time   Library中的类型,这样在启动线程时就不需要进行Windows数据类型和C   Run-time   Library中的数据类型之间的转化。减低了线程启动时的资源消耗和时间的消耗! 
3、在C++程序中,几乎都要用到new和delete,难道只有使用_beginthreadex()? 
不,因为MFC也是C++类库(只不过是Microsoft的C++类库,不是标准的C++类库),在MFC中也封装了new和delete两中运算符,所以用到new和delete的地方不一定非要使用_beginthreadex()   函数,用其他两个函数都可以! 

其实在程序中使用上面的哪个函数并不是绝对的,书的作者只不过是提了一个更佳的搭配方法,我在 
MFC程序中也经常使用_beginthreadex()和CreateThread()这两个函数,运行的效果也没有多大的区别,有的时候只是需要你额外的进行一些类型检查和其他的一些转化操作,其余没有其他不妥! 

 

原创粉丝点击