CreateThread, AfxBeginThread,_beginthread, _beginthreadex的区别

来源:互联网 发布:mac怎么看不到移动硬盘 编辑:程序博客网 时间:2024/05/29 19:59

原文地址::http://blog.csdn.net/miyunhong/article/details/4616982


一、转载自: 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。
uintptr_t _beginthread( 
   void( *start_address )( void * ),
   unsigned stack_size,
   void *arglist 
);
uintptr_t _beginthreadex( 
   void *security,
   unsigned stack_size,
   unsigned ( *start_address )( void * ),
   void *arglist,
   unsigned initflag,
   unsigned *thrdaddr 
);

_beginthreadex(   NULL,   0,   threadProc,   &pagram,   0,   
                                          (unsigned   int   *) idThread   );   

小节:实际上,这三个函数之间存在一定的调用关系,第一个纯粹一些,后两个完成自己相应的工作之后,调用前者实现线程的创建。其中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。

 

二、转载自: http://www.cppblog.com/bidepan2023/archive/2007/10/31/35627.html

当你打算实现一个多线程(非MFC)程序,你会选择一个单线程的CRT(C运行时库)吗?如果你的回答是NO, 那么会带来另外一个问题,你选择了CreateThread来创建一个线程吗? 大多数人也许会立刻回答YES。可是很不幸,这是错误的选择。
我先来说一下我的结论,待会告诉你为什么。

如果要作多线程(非MFC)程序,在主线程以外的任何线程内
- 使用malloc(),free(),new
- 调用stdio.h或io.h,包括fopen(),open(),getchar(),write(),printf(),errno
- 使用浮点变量和浮点运算函数
- 调用那些使用静态缓冲区的函数如: asctime(),strtok(),rand()等。
你就应该使用多线程的CRT并配合_beginthreadex(该函数只存在于多线程CRT), 其他情况下你可以使用单线程的CRT并配合CreateThread。

因为对产生的线程而言,_beginthreadex比之CreateThread会为上述操作多做额外的簿记工作,比如帮助strtok()为每个线程准备一份缓冲区。
然而多线程程序极少情况不使用上述那些函数(比如内存分配或者io),所以与其每次都要思考是要使用_beginthreadex还是CreateThread,不如就一棍子敲定_beginthreadex。

当然你也许会借助win32来处理内存分配和Io,这时候你确实可以以单线程crt配合CreateThread,因为io的重任已经从crt转交给了win32。这时通常你应该使用HeapAlloc,HeapFree来处理内存分配,用CreateFile或者GetStdHandle来处理Io。

还有一点比较重要的是_beginthreadex传回的虽然是个unsigned long,其实是个线程Handle(事实上_beginthreadex在内部就是调用了CreateThread),所以你应该用CloseHandle来结束他。千万不要使用ExitThread()来退出_beginthreadex创建的线程,那样会丧失释放簿记数据的机会,应该使用_endthreadex.

 

 

三、转载自:http://blog.csdn.net/idau7/archive/2007/08/25/1758712.aspx

这两天刚好手头有点事情跟线程相关, 刚好细细拜读jjh先生所译的win32线程大作, 有点不知所云, 起码是被弄的一愣一愣的, 偏听则暗, 果然如此, 只知其然而不知所以然, 恐怕过两天还是会忘记的. 就当写写心得记录了.

 

1.         已知windows下可以用如下方法创建线程.

1)        CreadThread(…). API

2)        _beginthread(…). CRT

3)        _beginthreadex(…). CRT

4)        AfxBeginThread(…). MFC

由于AfxBeginThread()同学勾搭MFC, 扬言誓死不分, 开除先.

_beginthreadex()和_beginthread()长的很像, 没什么直接血缘关系, 但都是CRT所提供的线程创建方式. 显著区别在于参数和返回值上.

2.         _beginthread(…)与_beginthreadex(…)区别.

1)        参数区别.

2)        返回值区别

_beginthread()返回-1表示失败, 而_beginthreadex()返回0表示失败

3)        实际过程区别.

3.         _beginthreadex(…)与CreadThread(…)区别.

1)        参数区别.

两者参数基本相同, 只是CreadThread()的参数是windows定义的win32数据类型, 而_beginthreadex()是标准C/C++的数据类型. 需要注意的是, CreateThread()的第三个参数函数指针是unsign long的, 而_beginthreadex()的第三个参数函数指针是unsign int的.

2)        返回值区别.

CreateThread(), 返回的是创建的线程的HANDLE,

_beginthreadex(), 返回的一个是unsigned long. 需通过reinterpret_cast<HANDLE>或(HANDLE)来强制转换.

3)        实际过程区别.

       一般不建议直接调用CreateThread(), 除非可以非常确定

4.         选择_beginthreadex()和CreateThread()的一般性规则.

不建议使用CreateThread(). 尤其当线程:

l         使用了malloc()/free(), new/delete的线程.

l         调用stdio.h或io.h中声明的任何函数.

l         使用浮点变量.

5.         为什么winCE上只能用CreateThread()?

我也不知道为什么….

 

参考文献:

1.         MSJ(Mircsofts System Journal) July 1999

http://www.microsoft.com/msj/0799/Win32/Win320799.aspx

2.         <Win32多线程程序设计>

3.         <windows核心编程>. 6章.

4.         oRbIt 的专栏. <CreateThread()和_beginthreadex()区别>.

http://blog.csdn.net/orbit/archive/2005/07/30/440118.aspx

向远处看的专栏. <CreateThread()和_beginthreadex()区别>

http://blog.csdn.net/xuxinshao/archive/2005/09/14/480797.aspx

搞不清谁的原创了….两位大仙都写原创…那…那肯定有个是引用的啊…要不难道是异灵事件?

5.         kind_li的专栏 kind_li 线程知识点.

http://blog.csdn.net/kind_li/archive/2003/04/03/10998.aspx

6.         运行时: 管理进程和线程

http://www-128.ibm.com/developerworks/cn/linux/sdk/rt/part7/index.html

7.         MSDN, _beginthreadex()跟_beginthread()的区别.

http://msdn2.microsoft.com/en-us/library/kdzttdcb(VS.71).aspx

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/idau7/archive/2007/08/25/1758712.aspx

 

 

四、转载自 http://820808.blog.51cto.com/328558/76160

 

五、来自msdn: 

ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_vccrt/html/0df64740-a978-4358-a88f-fb0702720091.htm

 

[c-sharp] view plaincopy
  1. // The following example uses _beginthread and _endthread  
  2.   
  3. // crt_BEGTHRD.C  
  4. // compile with: /MT /D "_X86_" /c  
  5. // processor: x86  
  6. #include <windows.h>  
  7. #include <process.h>    /* _beginthread, _endthread */  
  8. #include <stddef.h>  
  9. #include <stdlib.h>  
  10. #include <conio.h>  
  11.   
  12. void Bounce( void *ch );  
  13. void CheckKey( void *dummy );  
  14.   
  15. /* GetRandom returns a random integer between min and max. */  
  16. #define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))  
  17.   
  18. BOOL repeat = TRUE;     /* Global repeat flag and video variable */  
  19. HANDLE hStdOut;         /* Handle for console window */  
  20. CONSOLE_SCREEN_BUFFER_INFO csbi;    /* Console information structure */  
  21.   
  22. int main()  
  23. {  
  24.     CHAR    ch = 'A';  
  25.   
  26.     hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );  
  27.   
  28.     /* Get display screen's text row and column information. */  
  29.    GetConsoleScreenBufferInfo( hStdOut, &csbi );  
  30.   
  31.     /* Launch CheckKey thread to check for terminating keystroke. */  
  32.     _beginthread( CheckKey, 0, NULL );  
  33.   
  34.     /* Loop until CheckKey terminates program. */  
  35.     while( repeat )  
  36.     {  
  37.         /* On first loops, launch character threads. */  
  38.         _beginthread( Bounce, 0, (void *) (ch++)  );  
  39.   
  40.         /* Wait one second between loops. */  
  41.         Sleep( 1000L );  
  42.     }  
  43. }  
  44.   
  45. /* CheckKey - Thread to wait for a keystroke, then clear repeat flag. */  
  46. void CheckKey( void *dummy )  
  47. {  
  48.     _getch();  
  49.     repeat = 0;    /* _endthread implied */  
  50.   
  51. }  
  52.   
  53. /* Bounce - Thread to create and and control a colored letter that moves 
  54.  * around on the screen. 
  55.  * 
  56.  * Params: ch - the letter to be moved 
  57.  */  
  58. void Bounce( void *ch )  
  59. {  
  60.     /* Generate letter and color attribute from thread argument. */  
  61.     char    blankcell = 0x20;  
  62.     char    blockcell = (char) ch;  
  63.     BOOL    first = TRUE;  
  64.    COORD   oldcoord, newcoord;  
  65.    DWORD   result;  
  66.   
  67.   
  68.     /* Seed random number generator and get initial location. */  
  69.     srand( _threadid );  
  70.     newcoord.X = GetRandom( 0, csbi.dwSize.X - 1 );  
  71.     newcoord.Y = GetRandom( 0, csbi.dwSize.Y - 1 );  
  72.     while( repeat )  
  73.     {  
  74.         /* Pause between loops. */  
  75.         Sleep( 100L );  
  76.   
  77.         /* Blank out our old position on the screen, and draw new letter. */  
  78.         if( first )  
  79.             first = FALSE;  
  80.         else  
  81.          WriteConsoleOutputCharacter( hStdOut, &blankcell, 1, oldcoord, &result );  
  82.          WriteConsoleOutputCharacter( hStdOut, &blockcell, 1, newcoord, &result );  
  83.   
  84.         /* Increment the coordinate for next placement of the block. */  
  85.         oldcoord.X = newcoord.X;  
  86.         oldcoord.Y = newcoord.Y;  
  87.         newcoord.X += GetRandom( -1, 1 );  
  88.         newcoord.Y += GetRandom( -1, 1 );  
  89.   
  90.         /* Correct placement (and beep) if about to go off the screen. */  
  91.         if( newcoord.X < 0 )  
  92.             newcoord.X = 1;  
  93.         else if( newcoord.X == csbi.dwSize.X )  
  94.             newcoord.X = csbi.dwSize.X - 2;  
  95.         else if( newcoord.Y < 0 )  
  96.             newcoord.Y = 1;  
  97.         else if( newcoord.Y == csbi.dwSize.Y )  
  98.             newcoord.Y = csbi.dwSize.Y - 2;  
  99.   
  100.         /* If not at a screen border, continue, otherwise beep. */  
  101.         else  
  102.             continue;  
  103.         Beep( ((char) ch - 'A') * 100, 175 );  
  104.     }  
  105.     /* _endthread given to terminate */  
  106.     _endthread();  
  107. }  

 

[c-sharp] view plaincopy
  1. /*The following sample code demonstrates how you can use the thread handle returned by _beginthreadex with the synchronization API WaitForSingleObject. The main thread waits for the second thread to terminate before it continues. When the second thread calls _endthreadex, it causes its thread object to go to the signaled state. This allows the primary thread to continue running. This cannot be done with _beginthread and _endthread, because _endthread calls CloseHandle, destroying the thread object before it can be set to the signaled state.*/  
  2.   
  3.   
  4. // crt_begthrdex.cpp  
  5. // compile with: /MT  
  6. #include <windows.h>  
  7. #include <stdio.h>  
  8. #include <process.h>  
  9.   
  10. unsigned Counter;   
  11. unsigned __stdcall SecondThreadFunc( void* pArguments )  
  12. {  
  13.     printf( "In second thread.../n" );  
  14.   
  15.     while ( Counter < 1000000 )  
  16.         Counter++;  
  17.   
  18.     _endthreadex( 0 );  
  19.     return 0;  
  20. }   
  21.   
  22. int main()  
  23. {   
  24.     HANDLE hThread;  
  25.     unsigned threadID;  
  26.   
  27.     printf( "Creating second thread.../n" );  
  28.   
  29.     // Create the second thread.  
  30.     hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );  
  31.   
  32.     // Wait until second thread terminates. If you comment out the line  
  33.     // below, Counter will not be correct because the thread has not  
  34.     // terminated, and Counter most likely has not been incremented to  
  35.     // 1000000 yet.  
  36.     WaitForSingleObject( hThread, INFINITE );  
  37.     printf( "Counter should be 1000000; it is-> %d/n", Counter );  
  38.     // Destroy the thread object.  
  39.     CloseHandle( hThread );  
  40. }  

 

 

msdn :

ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.WIN32COM.v10.en/dllproc/base/creating_threads.htm

 

[c-sharp] view plaincopy
  1. The CreateThread function creates a new thread for a process. The creating thread must specify the starting address of the code that the new thread is to execute. Typically, the starting address is the name of a function defined in the program code (for more information, see ThreadProc). This function takes a single parameter and returns a DWORD value. A process can have multiple threads simultaneously executing the same function.   
  2.   
  3. /* 
  4. The following is a simple example that demonstrates how to create a new thread that executes the locally defined function, ThreadProc. The creating thread uses a dynamically allocated buffer to pass unique information to each instance of the thread function. It is the responsibility of the thread function to free the memory. 
  5.  
  6. The calling thread uses the WaitForMultipleObjects function to persist until all worker threads have terminated. Note that if you were to close the handle to a worker thread before it terminated, this does not terminate the worker thread. However, the handle will be unavailable for use in subsequent function calls.*/  
  7.  
  8.  
  9. #include <windows.h>  
  10. #include <strsafe.h>  
  11.  
  12. #define MAX_THREADS 3  
  13. #define BUF_SIZE 255  
  14.   
  15. typedef struct _MyData {  
  16.     int val1;  
  17.     int val2;  
  18. } MYDATA, *PMYDATA;  
  19.   
  20. DWORD WINAPI ThreadProc( LPVOID lpParam )   
  21. {   
  22.     HANDLE hStdout;  
  23.     PMYDATA pData;  
  24.   
  25.     TCHAR msgBuf[BUF_SIZE];  
  26.     size_t cchStringSize;  
  27.     DWORD dwChars;  
  28.   
  29.     hStdout = GetStdHandle(STD_OUTPUT_HANDLE);  
  30.     if( hStdout == INVALID_HANDLE_VALUE )  
  31.         return 1;  
  32.   
  33.     // Cast the parameter to the correct data type.  
  34.   
  35.     pData = (PMYDATA)lpParam;  
  36.   
  37.     // Print the parameter values using thread-safe functions.  
  38.   
  39.     StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d/n"),   
  40.         pData->val1, pData->val2);   
  41.     StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);  
  42.     WriteConsole(hStdout, msgBuf, cchStringSize, &dwChars, NULL);  
  43.   
  44.     // Free the memory allocated by the caller for the thread   
  45.     // data structure.  
  46.   
  47.     HeapFree(GetProcessHeap(), 0, pData);  
  48.   
  49.     return 0;   
  50. }   
  51.    
  52. void main()  
  53. {  
  54.     PMYDATA pData;  
  55.     DWORD dwThreadId[MAX_THREADS];  
  56.     HANDLE hThread[MAX_THREADS];   
  57.     int i;  
  58.   
  59.     // Create MAX_THREADS worker threads.  
  60.   
  61.     for( i=0; i<MAX_THREADS; i++ )  
  62.     {  
  63.         // Allocate memory for thread data.  
  64.   
  65.         pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,  
  66.                 sizeof(MYDATA));  
  67.   
  68.         if( pData == NULL )  
  69.             ExitProcess(2);  
  70.   
  71.         // Generate unique data for each thread.  
  72.   
  73.         pData->val1 = i;  
  74.         pData->val2 = i+100;  
  75.   
  76.         hThread[i] = CreateThread(   
  77.             NULL,              // default security attributes  
  78.             0,                 // use default stack size    
  79.             ThreadProc,        // thread function   
  80.             pData,             // argument to thread function   
  81.             0,                 // use default creation flags   
  82.             &dwThreadId[i]);   // returns the thread identifier   
  83.    
  84.         // Check the return value for success.   
  85.    
  86.         if (hThread[i] == NULL)   
  87.         {  
  88.             ExitProcess(i);  
  89.         }  
  90.     }  
  91.   
  92.     // Wait until all threads have terminated.  
  93.   
  94.     WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE);  
  95.   
  96.     // Close all thread handles upon completion.  
  97.   
  98.     for(i=0; i<MAX_THREADS; i++)  
  99.     {  
  100.         CloseHandle(hThread[i]);  
  101.     }  
  102. }  


原创粉丝点击