首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

CreateThread跟_beginthreadex() 有什么差别

2012-10-19 
CreateThread和_beginthreadex() 有什么差别?CreateThread和_beginthreadex() 有什么差别?[解决办法]_begi

CreateThread和_beginthreadex() 有什么差别?
CreateThread和_beginthreadex() 有什么差别?

[解决办法]
_beginthreadex()最终还是要调用CreateThread的。
===
[解决办法]
_beginthreadex是把CreateThread重新封装了一下,外部表现形式不同而已,没有本质差别。
[解决办法]
差别就在:
_beginthreadex用的是Multi-Theads C Runtime库
CreateThread是Windows API库
Note:
A thread that uses functions from the C run-time libraries should use the beginthread and endthread C run-time functions for thread management rather than CreateThread and ExitThread. Failure to do so results in small memory leaks when ExitThread is called.
[解决办法]
_beginthreadex是把CreateThread重新封装了一下,外部表现形式不同而已,没有本质差别。
[解决办法]
“让线程自然返回结束”的意思是不要用TerminateThread强制结束线程,然后线程函数自己return。
“不建议使用CreateThread”是担心你不知道关闭线程句柄,造成资源泄露。
[解决办法]

探讨
“让线程自然返回结束”的意思是不要用TerminateThread强制结束线程,然后线程函数自己return。
“不建议使用CreateThread”是担心你不知道关闭线程句柄,造成资源泄露。

[解决办法]
请注意,_beginthreadex和CreateThread还是有区别的,如果你要用到C runtime library(Multi-thread)库的函数,记得使用_beginthreadex而不是CreateThread, 对应的使用_endthreadex而不是CloseHandle()。
虽然在Windows,_beginthreadex的内部实现中调用了CreateThread(_endthreadex中调用CloseHandle)由于C runtime library中会一些全局变量,例如全局的buffer和错误标识等,_beginthreadex会负责为每个线程在TLS(Thread Local Storage)创建各自的线程相关全局变量,以防线程同步而导致的异常数据,而_endthreadex中则对应的释放为某线程申请的资源。


详细的信息,建议楼主阅读<Window核心编程>一书,里面有更详细的说明。
[解决办法]
探讨
请注意,_beginthreadex和CreateThread还是有区别的,如果你要用到C runtime library(Multi-thread)库的函数,记得使用_beginthreadex而不是CreateThread, 对应的使用_endthreadex而不是CloseHandle()。
虽然在Windows,_beginthreadex的内部实现中调用了CreateThread(_endthreadex中调用CloseHandle)由于C runtime library中会一些全局变量,例如全局的buffer和错误标识等,_beginthreadex会负责为每个线程在TLS(Thread Loc…

[解决办法]
没看过《Window核心编程》,不知道里面是怎么写的。

多线程库中是对一些库函数增加同步机制,例如多个线程同时用printf输出,如果没有使用多线程库,各个线程之间会有冲突,输出的字符有可能是混乱的;如果使用了多线程库,可以确保每次调用printf输出的字符是连续的。这类同步处理与是否使用_beginthreadex创建线程没有关系,用CreateThread创建线程。

_endthreadex可以释放为线程申请的资源,释放的方法就是CloseHandle关闭线程句柄。假如线程中用new分配一块内存而没有释放,退出线程时是不会自动释放的。
[解决办法]
后者对CRT进行了初始化
[解决办法]
探讨
没看过《Window核心编程》,不知道里面是怎么写的。

多线程库中是对一些库函数增加同步机制,例如多个线程同时用printf输出,如果没有使用多线程库,各个线程之间会有冲突,输出的字符有可能是混乱的;如果使用了多线程库,可以确保每次调用printf输出的字符是连续的。这类同步处理与是否使用_beginthreadex创建线程没有关系,用CreateThread创建线程。

_endthreadex可以释放为线程申请的资源,释放的方法就是CloseHandle关…

[解决办法]
探讨
Moonzero在我的进程安全退出问题的帖子中说:
发表于:2008-09-04 21:47:3424楼 得分:5
最好是设置标记,让线程自然返回结束
另外,不建议使用CreateThread创建一个线程,用_beginthreadex()
可以参考《windows核心编程》和《win32多线程程序设计》

我想知道为什么!


[解决办法]
"CreateThread函数是用来创建线程的Windows函数。不过,如果你正在编写C/C++代码,决不应该调用CreateThread。相反,应该使用Visual C++运行期库函数_beginthreadex。如果不使用Microsoft的Visual C++编译器,你的编译器供应商有它自己的CreateThred替代函数。不管这个替代函数是什么,你都必须使用。"
"_beginthreadex函数的参数列表与CreateThread函数的参数列表是相同的,但是参数名和类型并不完全相同。这是因为Microsoft的C/C++运行期库的开发小组认为, C/C++运行期函数不应该对Windows数据类型有任何依赖。_beginthreadex函数也像CreateThread那样,返回新创建的线程的句柄。因此,如果调用源代码中的CreateThread,就很容易用对_beginthreadex的调用全局取代所有这些调用。不过,由于数据类型并不完全相同,所以必须进行某种转换,使编译器运行得顺利些。"


"下面是关于_beginthreadex的一些要点:
? 每个线程均获得由C/C++运行期库的堆栈分配的自己的tiddata内存结构。(tiddata结构位于Mtdll.h文件中的Visual C++源代码中)。
? 传递给_beginthreadex的线程函数的地址保存在tiddata内存块中。传递给该函数的参数也保存在该数据块中。
? _beginthreadex确实从内部调用CreateThread,因为这是操作系统了解如何创建新线程的唯一方法。
? 当调用CreatetThread时,它被告知通过调用_threadstartex而不是pfnStartAddr来启动执行新线程。还有,传递给线程函数的参数是tiddata结构而不是pvParam的地址。
? 如果一切顺利,就会像CreateThread那样返回线程句柄。如果任何操作失败了,便返回NULL。"
"也许你想知道,如果调用CreateThread,而不是调用C/C++运行期库的_beginthreadex来创建新线程,将会发生什么情况。当一个线程调用要求tiddata结构的C/C++运行期库函数时,将会发生下面的一些情况(大多数C/C++运行期库函数都是线程安全函数,不需要该结构)。首先,C/C++运行期库函数试图(通过调用TlsGetValue)获取线程的数据块的地址。如果返回NULL作为tiddata块的地址,调用线程就不拥有与该地址相关的tiddata块。这时,C/C++运行期库函数就在现场为调用线程分配一个tiddata块,并对它进行初始化。然后该tiddata块(通过TlsSetValue)与线程相关联。此时,只要线程在运行,该tiddata将与线程待在一起。这时,C/C++运行期库函数就可以使用线程的tiddata块,而且将来被调用的所有C/C++运行期函数也能使用tiddata块。
当然,这看来有些奇怪,因为线程运行时几乎没有任何障碍。不过,实际上还是存在一些问题。首先,如果线程使用C/C++运行期库的signal函数,那么整个进程就会终止运行,因为结构化异常处理帧尚未准备好。第二,如果不是调用_endthreadex来终止线程的运行,那么数据块就不会被撤消,内存泄漏就会出现(那么谁还为使用CreateThread函数创建的线程来调用_endthreadex呢?)。
注意如果程序模块链接到多线程DLL版本的C/C++运行期库,那么当线程终止运行并释放tiddata块(如果已经分配了tiddata块的话)时,该运行期库会收到一个DLL_THREAD_DETACH通知。尽管这可以防止tiddata块的泄漏,但是强烈建议使用_beginthreadex而不是使用Createthread来创建线程。"

以上是《windows核心编程》对Createthread 和 _beginthreadex 的部分讲解。
[解决办法]
每个线程函数在启动的时候,它的参数就是一个LPVOID,主线程可以为子线程传递任意类型的值,为何还要使用TlsSetValue,搞个什么线程局部存储器,不是多此一举吗?

回18楼的,怎么可能不需要线程同步呢?一个读线程在开始之前需要写线程写入数据,没有前一个线程把事情做好,后面的线程就没办开工。就算使用了_beginthreadex(),也还要需要线程同步的吧。把全局数据都封装到线程里面,你叫线程怎么通讯?一个进程也不可能开这么套间进程,让别的线程发消息过来处理?

_beginthreadex定义了c++ runtime线程启用函数,那我在线程函数中new了一个变量,那个TLS怎么知道我这个线程已分配的资源,并在必要时释放资源呢?是不是只能事先 new的方式把资源分配好,然后使用TLSSetValue,把它交给线程,才能做到_endThreadex的自动释放资源呢?



[解决办法]
如果你使用C/C++开发程序,建议使用_beginthreadex 
1、不依赖于操作系统,具有更好的移植性
2、因为C/C++运行库对每个新开增的线程维护了一个数据结构,如果使用CreateThread就不会有这个结构,
因此当你使用一些C/C++库函数时会有错误
3、_beginthreadex只存在于多线程版本中,这样当你使用了错误的CRT时就会出出链接错误。
另外新代码不要使用_beginthread 和 _endthread

热点排行