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

CreateThread与_beginthreadex的差别和应用场景

2012-11-08 
CreateThread与_beginthreadex的区别和应用场景我查了好多网上的资料,知道这两者的区别是一个是winapi,一

CreateThread与_beginthreadex的区别和应用场景
我查了好多网上的资料,知道这两者的区别是一个是winapi,一个是c run-time 库。我想问的问题是:
1、winapi与c run-time库有何区别?
2、这两者的应用场景有何不同?我发现在我们的产品代码中只用到了CreateThread,根本没有使用_beginthreadex这个函数。

[解决办法]
1,运行时库最终也是调用API
2,运行时库做的事情更多


[解决办法]
如果你产品中全用WinAPI,那么CreateThread自然没问题

某些库函数在CreateThread下会有问题,请参见《Windows核心编程》,所以使用了线程不安全的库函数和修改errno的库函数,请使用_beginthreadex
[解决办法]
1 _beginthreadex初始化线程的运行库环境,比如线程的errno。
2 C/C++程序最简单的规则就是 禁止使用CreateThread。
 否则C运行库的不少函数都是不能使用的,太容易误用了。
[解决办法]
只要连接到多线程环境的CRT,即使是CreateThread也能保证库函数正确调用,但是在线程关闭的时候,这会导致由库函数引起的内存泄露。因此微软引入了_beginthread/_endthread和_beginthreadex/_endthreadex来解决内存泄露的问题。
[解决办法]
CreateThread本身没有什么问题,在遇到下面等等函数的时候会现场创建tiddata,
_doserrno, strtok, _wcstok, strerror, _strerror, tmpnam, tmpfile.....
你自己调用_endthreadex释放tiddata就好了。
如果你不确保你记得调用_endthreadex或者觉得别扭,那就换成_beginthreadex。
另外,如果你不想发生像下面这个帖子中可能让你困惑的报错的话,就用_benginthreadex吧
http://topic.csdn.net/u/20120905/14/0bc482cc-0f91-4e18-b6b2-28811ff9b26c.html

[解决办法]
《Windows核心编程》

[解决办法]
最好的方法是看_beginthreadex()的实现,看看它的比CreateThread多做了些什么操作

C/C++ code
/****_beginthreadex() - Create a child thread**Purpose:*       Create a child thread.**Entry:*       *** Same parameters as the Win32 API CreateThread() ****       security = security descriptor for the new thread*       stacksize = size of stack*       initialcode = pointer to thread's startup code address*               must be a __stdcall function returning an unsigned.*       argument = argument to be passed to new thread*       createflag = flag to create thread in a suspended state*       thrdaddr = points to an int to receive the ID of the new thread**Exit:*       *** Same as the Win32 API CreateThread() *****       success = handle for new thread if successful**       failure = 0 in case of error, errno and _doserrno are set**Exceptions:**Notes:*       This routine is more like the Win32 API CreateThread() than it*       is like the C run-time routine _beginthread().  Ditto for*       _endthreadex() and the Win32 API ExitThread() versus _endthread().**       Differences between _beginthread/_endthread and the "ex" versions:**         1)  _beginthreadex takes the 3 extra parameters to CreateThread*             which are lacking in _beginthread():*               A) security descriptor for the new thread*               B) initial thread state (running/asleep)*               C) pointer to return ID of newly created thread**         2)  The routine passed to _beginthread() must be __cdecl and has*             no return code, but the routine passed to _beginthreadex()*             must be __stdcall and returns a thread exit code.  _endthread*             likewise takes no parameter and calls ExitThread() with a*             parameter of zero, but _endthreadex() takes a parameter as*             thread exit code.**         3)  _endthread implicitly closes the handle to the thread, but*             _endthreadex does not!**         4)  _beginthread returns -1 for failure, _beginthreadex returns*             0 for failure (just like CreateThread).********************************************************************************/_MCRTIMP uintptr_t __cdecl _beginthreadex (        void *security,        unsigned stacksize,        unsigned (__CLR_OR_STD_CALL * initialcode) (void *),        void * argument,        unsigned createflag,        unsigned *thrdaddr        ){        _ptiddata ptd;                  /* pointer to per-thread data */        uintptr_t thdl;                 /* thread handle */        unsigned long err = 0L;     /* Return from GetLastError() */        unsigned dummyid;               /* dummy returned thread ID */        /* validation section */        _VALIDATE_RETURN(initialcode != NULL, EINVAL, 0);        /* Initialize FlsGetValue function pointer */        __set_flsgetvalue();        /*         * Allocate and initialize a per-thread data structure for the to-         * be-created thread.         */        if ( (ptd = (_ptiddata)_calloc_crt(1, sizeof(struct _tiddata))) == NULL )                goto error_return;        /*         * Initialize the per-thread data         */        _initptd(ptd, _getptd()->ptlocinfo);        ptd->_initaddr = (void *) initialcode;        ptd->_initarg = argument;        ptd->_thandle = (uintptr_t)(-1);#if defined (_M_CEE) || defined (MRTDLL)        if(!_getdomain(&(ptd->__initDomain)))        {            goto error_return;        }#endif  /* defined (_M_CEE) || defined (MRTDLL) */        /*         * Make sure non-NULL thrdaddr is passed to CreateThread         */        if ( thrdaddr == NULL )                thrdaddr = &dummyid;        /*         * Create the new thread using the parameters supplied by the caller.         */        if ( (thdl = (uintptr_t)              CreateThread( (LPSECURITY_ATTRIBUTES)security,                            stacksize,                            _threadstartex,                            (LPVOID)ptd,                            createflag,                            (LPDWORD)thrdaddr))             == (uintptr_t)0 )        {                err = GetLastError();                goto error_return;        }        /*         * Good return         */        return(thdl);        /*         * Error return         */error_return:        /*         * Either ptd is NULL, or it points to the no-longer-necessary block         * calloc-ed for the _tiddata struct which should now be freed up.         */        _free_crt(ptd);        /*         * Map the error, if necessary.         *         * Note: this routine returns 0 for failure, just like the Win32         * API CreateThread, but _beginthread() returns -1 for failure.         */        if ( err != 0L )                _dosmaperr(err);        return( (uintptr_t)0 );} 

热点排行
Bad Request.