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”是担心你不知道关闭线程句柄,造成资源泄露。
[解决办法]
"下面是关于_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