CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
花落谁家,你作主! 盛大widget设计大赛英雄榜
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  基础类

创建线程的两种方式

楼主frankelin(飞鹰)2005-03-10 21:07:57 在 VC/MFC / 基础类 提问

今天去面试,考官问我创建线程的两种方式,我知道由一个是CreateThread.另一种是什么呢??????? 问题点数:0、回复次数:5Top

1 楼fireseed(【VC无敌,英明神武,千秋万代,一统江湖!】—奶油狗)回复于 2005-03-10 22:53:53 得分 0

Run-Time   Library   Reference        
   
  _beginthread,   _beginthreadexSee   Also  
  Process   and   Environment   Control   Routines   |   _endthread   |   abort   |   exit   |   Run-Time   Routines   and   .NET   Framework   Equivalents  
  Requirements  
  Routine   Required   header   Compatibility    
  _beginthread   <process.h>   Win   98,   Win   Me,   Win   NT,   Win   2000,   Win   XP      
  _beginthreadex   <process.h>   Win   98,   Win   Me,   Win   NT,   Win   2000,   Win   XP      
   
  For   additional   compatibility   information,   see   Compatibility   in   the   Introduction.  
   
  Libraries  
   
  Multithreaded   versions   of   the   C   run-time   libraries   only.  
   
  To   use   _beginthread   or   _beginthreadex,   the   application   must   link   with   one   of   the   multithreaded   C   run-time   libraries.  
  Create   a   thread.  
   
  uintptr_t   _beginthread(    
        void(   __cdecl   *start_address   )(   void   *   ),  
        unsigned   stack_size,  
        void   *arglist    
  );  
  uintptr_t   _beginthreadex(    
        void   *security,  
        unsigned   stack_size,  
        unsigned   (   __stdcall   *start_address   )(   void   *   ),  
        void   *arglist,  
        unsigned   initflag,  
        unsigned   *thrdaddr    
  );  
  Parameters  
  start_address    
  Start   address   of   routine   that   begins   execution   of   new   thread.    
  stack_size    
  Stack   size   for   new   thread   or   0.    
  arglist    
  Argument   list   to   be   passed   to   new   thread   or   NULL.    
  security    
  Pointer   to   a   SECURITY_ATTRIBUTES   structure   that   determines   whether   the   returned   handle   can   be   inherited   by   child   processes.   If   NULL,   the   handle   cannot   be   inherited.   Must   be   NULL   for   Windows   95   applications.    
  initflag    
  Initial   state   of   new   thread   (0   for   running   or   CREATE_SUSPENDED   for   suspended);   use   ResumeThread   to   execute   the   thread.    
  thrdaddr    
  Points   to   a   32-bit   variable   that   receives   the   thread   identifier.    
  Return   Value  
  If   successful,   each   of   these   functions   returns   a   handle   to   the   newly   created   thread.   _beginthread   returns   –1L   on   an   error,   in   which   case   errno   is   set   to   EAGAIN   if   there   are   too   many   threads,   or   to   EINVAL   if   the   argument   is   invalid   or   the   stack   size   is   incorrect.   _beginthreadex   returns   0   on   an   error,   in   which   case   errno   and   _doserrno   are   set.  
   
  See   Standard   Types   for   more   information   on   uintptr_t.  
   
  See   _doserrno,   errno,   _sys_errlist,   and   _sys_nerr   for   more   information   on   these   and   other   return   codes.  
   
  Remarks  
  The   _beginthread   function   creates   a   thread   that   begins   execution   of   a   routine   at   start_address.   The   routine   at   start_address   must   use   the   __cdecl   calling   convention   and   should   have   no   return   value.   When   the   thread   returns   from   that   routine,   it   is   terminated   automatically.   For   more   information   on   threads,   see   Multithreading.  
   
  _beginthreadex   resembles   the   Win32   CreateThread   API   more   closely   than   _beginthread   does.   _beginthreadex   differs   from   _beginthread   in   the   following   ways:    
   
  _beginthreadex   has   three   additional   parameters:   initflag,   security,   threadaddr.   The   new   thread   can   be   created   in   a   suspended   state,   with   a   specified   security   (Windows   NT   only),   and   can   be   accessed   using   thrdaddr,   which   is   the   thread   identifier.    
  The   routine   at   start_address   passed   to   _beginthreadex   must   use   the   __stdcall   calling   convention   and   must   return   a   thread   exit   code.    
  _beginthreadex   returns   0   on   failure,   rather   than   –1L.    
  A   thread   created   with   _beginthreadex   is   terminated   by   a   call   to   _endthreadex.    
  The   _beginthreadex   function   gives   you   more   control   over   how   the   thread   is   created   than   _beginthread   does.   The   _endthreadex   function   is   also   more   flexible.   For   example,   with   _beginthreadex,   you   can   use   security   information,   set   the   initial   state   of   the   thread   (running   or   suspended),   and   get   the   thread   identifier   of   the   newly   created   thread.   You   are   also   able   to   use   the   thread   handle   returned   by   _beginthreadex   with   the   synchronization   APIs,   which   you   cannot   do   with   _beginthread.    
   
  It   is   safer   to   use   _beginthreadex   than   _beginthread.   If   the   thread   spawned   by   _beginthread   exits   quickly,   the   handle   returned   to   the   caller   of   _beginthread   may   be   invalid   or,   worse,   point   to   another   thread.   However,   the   handle   returned   by   _beginthreadex   has   to   be   closed   by   the   caller   of   _beginthreadex,   so   it   is   guaranteed   to   be   a   valid   handle   if   _beginthreadex   did   not   return   an   error.    
   
  You   can   call   _endthread   or   _endthreadex   explicitly   to   terminate   a   thread;   however,   _endthread   or   _endthreadex   is   called   automatically   when   the   thread   returns   from   the   routine   passed   as   a   parameter.   Terminating   a   thread   with   a   call   to   endthread   or   _endthreadex   helps   to   ensure   proper   recovery   of   resources   allocated   for   the   thread.  
   
  _endthread   automatically   closes   the   thread   handle   (whereas   _endthreadex   does   not).   Therefore,   when   using   _beginthread   and   _endthread,   do   not   explicitly   close   the   thread   handle   by   calling   the   Win32   CloseHandle   API.   This   behavior   differs   from   the   Win32   ExitThread   API.  
   
  Note       For   an   executable   file   linked   with   LIBCMT.LIB,   do   not   call   the   Win32   ExitThread   API;   this   prevents   the   run-time   system   from   reclaiming   allocated   resources.   _endthread   and   _endthreadex   reclaim   allocated   thread   resources   and   then   call   ExitThread.  
  The   operating   system   handles   the   allocation   of   the   stack   when   either   _beginthread   or   _beginthreadex   is   called;   you   do   not   need   to   pass   the   address   of   the   thread   stack   to   either   of   these   functions.   In   addition,   the   stack_size   argument   can   be   0,   in   which   case   the   operating   system   uses   the   same   value   as   the   stack   specified   for   the   main   thread.  
   
  arglist   is   a   parameter   to   be   passed   to   the   newly   created   thread.   Typically   it   is   the   address   of   a   data   item,   such   as   a   character   string.   arglist   may   be   NULL   if   it   is   not   needed,   but   _beginthread   and   _beginthreadex   must   be   provided   with   some   value   to   pass   to   the   new   thread.   All   threads   are   terminated   if   any   thread   calls   abort,   exit,   _exit,   or   ExitProcess.  
   
  Requirements  
  Routine   Required   header   Compatibility    
  _beginthread   <process.h>   Win   98,   Win   Me,   Win   NT,   Win   2000,   Win   XP      
  _beginthreadex   <process.h>   Win   98,   Win   Me,   Win   NT,   Win   2000,   Win   XP      
   
  For   additional   compatibility   information,   see   Compatibility   in   the   Introduction.  
   
  Libraries  
   
  Multithreaded   versions   of   the   C   run-time   libraries   only.  
   
  To   use   _beginthread   or   _beginthreadex,   the   application   must   link   with   one   of   the   multithreaded   C   run-time   libraries.  
  Top

2 楼fireseed(【VC无敌,英明神武,千秋万代,一统江湖!】—奶油狗)回复于 2005-03-10 22:53:57 得分 0

 
  Example  
  The   following   example   uses   _beginthread   and   _endthread.  
   
  //   crt_BEGTHRD.C  
  //   compile   with:   /MT   /D   "_X86_"   /c  
  #include   <windows.h>  
  #include   <process.h>         /*   _beginthread,   _endthread   */  
  #include   <stddef.h>  
  #include   <stdlib.h>  
  #include   <conio.h>  
   
  void   Bounce(   void   *ch   );  
  void   CheckKey(   void   *dummy   );  
   
  /*   GetRandom   returns   a   random   integer   between   min   and   max.   */  
  #define   GetRandom(   min,   max   )   ((rand()   %   (int)(((max)   +   1)   -   (min)))   +   (min))  
   
  BOOL   repeat   =   TRUE;           /*   Global   repeat   flag   and   video   variable   */  
  HANDLE   hStdOut;                   /*   Handle   for   console   window   */  
  CONSOLE_SCREEN_BUFFER_INFO   csbi;         /*   Console   information   structure   */  
   
  int   main()  
  {  
          CHAR         ch   =   'A';  
   
          hStdOut   =   GetStdHandle(   STD_OUTPUT_HANDLE   );  
   
          /*   Get   display   screen's   text   row   and   column   information.   */  
        GetConsoleScreenBufferInfo(   hStdOut,   &csbi   );  
   
          /*   Launch   CheckKey   thread   to   check   for   terminating   keystroke.   */  
          _beginthread(   CheckKey,   0,   NULL   );  
   
          /*   Loop   until   CheckKey   terminates   program.   */  
          while(   repeat   )  
          {  
                  /*   On   first   loops,   launch   character   threads.   */  
                  _beginthread(   Bounce,   0,   (void   *)   (ch++)     );  
   
                  /*   Wait   one   second   between   loops.   */  
                  Sleep(   1000L   );  
          }  
  }  
   
  /*   CheckKey   -   Thread   to   wait   for   a   keystroke,   then   clear   repeat   flag.   */  
  void   CheckKey(   void   *dummy   )  
  {  
          _getch();  
          repeat   =   0;         /*   _endthread   implied   */  
   
  }  
   
  /*   Bounce   -   Thread   to   create   and   and   control   a   colored   letter   that   moves  
    *   around   on   the   screen.  
    *  
    *   Params:   ch   -   the   letter   to   be   moved  
    */  
  void   Bounce(   void   *ch   )  
  {  
          /*   Generate   letter   and   color   attribute   from   thread   argument.   */  
          char         blankcell   =   0x20;  
          char         blockcell   =   (char)   ch;  
          BOOL         first   =   TRUE;  
        COORD       oldcoord,   newcoord;  
        DWORD       result;  
   
   
          /*   Seed   random   number   generator   and   get   initial   location.   */  
          srand(   _threadid   );  
          newcoord.X   =   GetRandom(   0,   csbi.dwSize.X   -   1   );  
          newcoord.Y   =   GetRandom(   0,   csbi.dwSize.Y   -   1   );  
          while(   repeat   )  
          {  
                  /*   Pause   between   loops.   */  
                  Sleep(   100L   );  
   
                  /*   Blank   out   our   old   position   on   the   screen,   and   draw   new   letter.   */  
                  if(   first   )  
                          first   =   FALSE;  
                  else  
                    WriteConsoleOutputCharacter(   hStdOut,   &blankcell,   1,   oldcoord,   &result   );  
                    WriteConsoleOutputCharacter(   hStdOut,   &blockcell,   1,   newcoord,   &result   );  
   
                  /*   Increment   the   coordinate   for   next   placement   of   the   block.   */  
                  oldcoord.X   =   newcoord.X;  
                  oldcoord.Y   =   newcoord.Y;  
                  newcoord.X   +=   GetRandom(   -1,   1   );  
                  newcoord.Y   +=   GetRandom(   -1,   1   );  
   
                  /*   Correct   placement   (and   beep)   if   about   to   go   off   the   screen.   */  
                  if(   newcoord.X   <   0   )  
                          newcoord.X   =   1;  
                  else   if(   newcoord.X   ==   csbi.dwSize.X   )  
                          newcoord.X   =   csbi.dwSize.X   -   2;  
                  else   if(   newcoord.Y   <   0   )  
                          newcoord.Y   =   1;  
                  else   if(   newcoord.Y   ==   csbi.dwSize.Y   )  
                          newcoord.Y   =   csbi.dwSize.Y   -   2;  
   
                  /*   If   not   at   a   screen   border,   continue,   otherwise   beep.   */  
                  else  
                          continue;  
                  Beep(   ((char)   ch   -   'A')   *   100,   175   );  
          }  
          /*   _endthread   given   to   terminate   */  
          _endthread();  
  }  
  Input  
  press   any   key   to   end  
  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.  
   
  //   crt_begthrdex.cpp  
  //   compile   with:   /MT  
  #include   <windows.h>  
  #include   <stdio.h>  
  #include   <process.h>  
   
  unsigned   Counter;    
  unsigned   __stdcall   SecondThreadFunc(   void*   pArguments   )  
  {  
          printf(   "In   second   thread...\n"   );  
   
          while   (   Counter   <   1000000   )  
                  Counter++;  
   
          _endthreadex(   0   );  
          return   0;  
  }    
   
  int   main()  
  {    
          HANDLE   hThread;  
          unsigned   threadID;  
   
          printf(   "Creating   second   thread...\n"   );  
   
          //   Create   the   second   thread.  
          hThread   =   (HANDLE)_beginthreadex(   NULL,   0,   &SecondThreadFunc,   NULL,   0,   &threadID   );  
   
          //   Wait   until   second   thread   terminates.   If   you   comment   out   the   line  
          //   below,   Counter   will   not   be   correct   because   the   thread   has   not  
          //   terminated,   and   Counter   most   likely   has   not   been   incremented   to  
          //   1000000   yet.  
          WaitForSingleObject(   hThread,   INFINITE   );  
          printf(   "Counter   should   be   1000000;   it   is->   %d\n",   Counter   );  
          //   Destroy   the   thread   object.  
          CloseHandle(   hThread   );  
  }  
  Output  
  Creating   second   thread...  
  In   second   thread...  
  Counter   should   be   1000000;   it   is->   1000000  
  See   Also  
  Process   and   Environment   Control   Routines   |   _endthread   |   abort   |   exit   |   Run-Time   Routines   and   .NET   Framework   Equivalents  
   
   
   
  --------------------------------------------------------------------------------  
   
  Send   feedback   on   this   topic   to   Microsoft  
   
  &copy;   Microsoft   Corporation.   All   rights   reserved.  
  Top

3 楼forpku(理工娃娃鱼)回复于 2005-03-10 23:07:36 得分 0

上面说的没错,但是都是英文,还麻烦的很  
  偶来大概说一下  
  一个就是你说的createthread()函数。这个函数比较正式一点,里面的参数就比较详细的安全性描述。还有一个就是_beginthread()函数了,这个是上面哪个函数的简化版本,windows出这个函数的原因是为了让这个函数可以运行在不同的平台下,所以它的参数都是c/c++的基础数据类型。它们若创建成功,都会返回创建的线程的HANDLE。2个函数里面都有一个参数就是传递的参数的指针。在普通的、简单的win32下的简单应用,建议用后面这个参数。在大一点的工程或者MFC程序应用中,最好用前面一个函数,关于线程有很多东西是直接和操作系统低层相关的,比如线程同步,共享内存等。建议好好深入一下,可以收获很多的Top

4 楼tudou614(魔蟹座的SATAN)回复于 2005-03-11 02:10:28 得分 0

GZTop

5 楼crystal521(【云淡风轻】)回复于 2005-03-11 09:17:57 得分 0

_beginthread((void   (*)(void   *))ReceiveMsg,0,(void   *)&hwnd)  
  还可以用CWinThread*   AfxBeginThread(...)Top

相关问题

  • 创建线程!!!
  • 创建线程
  • 线程中创建一个快捷方式,好慢,这是为什么?
  • 用CreateThread(...)创建线程...?
  • 如何创建多线程
  • 创建线程问题。
  • 请问创建线程时,怎样给线程传递参数??
  • 一个在主线程中的子线程能否在线程函数中创建自己的子线程呢?
  • 当前线程A创建另一个线程B后,怎样让线程A等待直到线程B完成?
  • 在vc中动态创建线程

关键词

  • .net framework
  • win32
  • 函数
  • 线程
  • newcoord
  • beginthread
  • checkkey
  • beginthreadex
  • getrandom
  • oldcoord

得分解答快速导航

  • 帖主:frankelin

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo