C++线程编程解析+事例

1:创建线程函数介绍


在window系统中编写控制台程序,创建线程

使用CreateThread()函数创建,则线程函数必须申明为DWORD WINAPI;

使用_beginthreadex()创建,则线程函数必须申明为unsigned int WINAPI;

并需要设置环境:工程->设置->C/C++->Code Generation->Use run-time libray->选 Debug Multithread(多线程),或 Multithread.

将类成员函数作为线程函数方式:

1.将类成员申明为STATIC成员函数;

2.将函数申明为类的友元函数;


   1.1  CreateThread函数

“CreateThread函数是用来创建线程的Windows函数不过,如果你正在编写C/C++代码,决不应该调用CreateThread。相反,应该使用Visual C++运行期库函数_beginthreadex。如果不使用Microsoft的Visual C++编译器,你的编译器供应商有它自己的CreateThred替代函数。不管这个替代函数是什么,你都必须使用。”

HANDLE CreateThread

( LPSECURITY_ATTRIBUTES lpsa,

 DWORD cbStack, 

 LPTHREAD_START_ROUTINE lpStartAddr,

 LPVOID lpvThreadParam,

 DWORD fdwCreate,

 LPDWORD lpIDThread);

具体解释为:

 //第1个参数:lpsa:线程句柄的安全属性,比如子进程是否可以继承这个线程句柄,一般情况设置为NULL

 //第1个参数:cbStack:线程栈大小,一般取0表示默认大小

 //第3个参数:lpStartAddr:线程入口函数

                 typedef DWORD (__stdcall *LPTHREAD_START_ROUTINE) ( void* lpThreadParameter );

                在win32程序中默认的调用函数约定就是WINAPI ,__stdcall = WINAPI 

                因此你可以声明你的入口函数为:DWORD WINAPI ThreadProc( void* lpParamete) {//线程中你要做的事情}

 //第4个参数:lpvThreadParam:就是线程入口函数的参数,就是ThreadProc( void* lpParamete) 的参数

 //第5个参数:fdwCreate:控制线程创建的标志一般为0,表示线程立即启动。如果你想创建之后把线程挂起来可以传入CREATE_SUSPENDED ,传入这个参数你需要再适当的地方调用                              ResumeThread 启动线程

 //第6个参数lpIDThread:是线程ID返回值,这个用来接收线程返回的ID。

   1.2 _beginthreadex()函数

参数说明:

unsigned long _beginthreadex( void *security, unsigned stack_size, unsigned ( __stdcall *start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr );

 //第1个参数:安全属性,NULL为默认安全属性
 //第2个参数:指定线程堆栈的大小。如果为0,则线程堆栈大小和创建它的线程的相同。一般用0
 //第3个参数:指定线程函数的地址,也就是线程调用执行的函数地址(用函数名称即可,函数名称就表示地址)
 //第4个参数:传递给线程的参数的指针,可以通过传入对象的指针,在线程函数中再转化为对应类的指针
 //第5个参数:线程初始状态,0:立即运行;CREATE_SUSPEND:suspended(悬挂)
 //第6个参数:用于记录线程ID的地址



C运行库_beginthreadex()。他经过一些处理后,再调用CreateThread(),因此比CreateThread安全一些。如果要强制结束的话也最好用_endthreadex 结束,因为他也要一些处理。如果不是调用_endthreadex来终止线程的运行,那么数据块就不会被撤消,内存泄漏就会出现

另外还有AfxBeginThread()

具体区别请参照:http://hi.baidu.com/kings0527/blog/item/11838d02a1b3bbe608fa93ff.html

2:线程创建的例子

以下只是框架 

全局变量  HANDLE g_Thread ;

 在类CA中  

 class CA
{


public :

  int m_member;  //成员变量 
   static WINAPI UINT  threadFunc(LPVOID P); //必须是静态的 或者全局的 
   

   void OnInitDialog()  

{

 g_Thread = (HANDLE)_beginthreadex(NULL, 0, ThreadFun,this, 0, &threadID);  //this 参数的传递 

if (g_Thread==0)
{
          GetLastError(); 

   .............
            MessageBox(_T("_beginthreadex 创建失败!"));
           _endthread(g_Thread);
        

}

else
MessageBox(_T("_beginthreadex 创建成功!"));

}

UINT threadFunc(LPVOID p)
{
   CA *obj = p;
   obj->m_member ;   //成员变量的传递
}

更好的例子参照:http://blog.csdn.net/maopig/article/details/6772258   详细的解释  


3:线程的同步
 

    1临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。 

    2互斥量:为协调共同对一个共享资源的单独访问而设计的。 

    3信号量:为控制一个具有有限数量用户资源而设计。 

    4事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。


  互斥体代码例子:

  
[cpp]  view plain  copy
 print ?
  1. <pre name="code" class="cpp">//这是2个线程模拟卖火车票的小程序  
  2. #include <windows.h>  
  3. #include <iostream.h>  
  4.   
  5. DWORD WINAPI Fun1Proc(LPVOID lpParameter);//thread data  
  6. DWORD WINAPI Fun2Proc(LPVOID lpParameter);//thread data  
  7.   
  8. int index=0;  
  9. int tickets=10;  
  10. HANDLE hMutex;  
  11. void main()  
  12. {  
  13.     HANDLE hThread1;  
  14.     HANDLE hThread2;  
  15.     //创建线程  
  16.   
  17.     hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);  
  18.     hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);  
  19.     CloseHandle(hThread1);  
  20.     CloseHandle(hThread2);  
  21.   
  22.     //创建互斥对象  
  23.     hMutex=CreateMutex(NULL,TRUE,"tickets");  
  24.     if (hMutex)  
  25.     {  
  26.         if (ERROR_ALREADY_EXISTS==GetLastError())//得到错误:已经存在  
  27.         {  
  28.         // 如果已有互斥量存在则释放句柄并复位互斥量  
  29.         CloseHandle(m_hMutex);  
  30.         m_hMutex = NULL;  
  31.             cout<<"only one instance can run!"<<endl;  
  32.             return;  
  33.         }  
  34.     }  
  35.     WaitForSingleObject(hMutex,INFINITE);  
  36.     ReleaseMutex(hMutex);//申请了两次就要施放两次(没搞懂在哪里申请了两次?难道建立一次,wait也算一次?)  
  37.     ReleaseMutex(hMutex);//谁申请谁施放  
  38.       
  39.     Sleep(4000);//让主线程睡4秒,让其他线程有时间执行完他们的代码,如果不睡就会出现其他线程执行不完或出错的情况,但时如果不知道线程需要多少时间执行,那应该写多少时间?  
  40. }  
  41. //线程1的入口函数  
  42. DWORD WINAPI Fun1Proc(LPVOID lpParameter)//thread data  
  43. {  
  44.     while (true)//无限循环线程  
  45.     {  
  46.         WaitForSingleObject(hMutex,INFINITE);//得到互斥体才能执行  
  47.         if (tickets>0)  
  48.         {  
  49.             Sleep(1);  
  50.             cout<<"thread1 sell ticket :"<<tickets--<<endl;  
  51.         }  
  52.         else  
  53.             break;  
  54.         ReleaseMutex(hMutex);//施放互斥体  
  55.     }  
  56.   
  57.     return 0;  
  58. }  
  59. //线程2的入口函数  
  60. DWORD WINAPI Fun2Proc(LPVOID lpParameter)//thread data  
  61. {  
  62.     while (true)  
  63.     {  
  64.         WaitForSingleObject(hMutex,INFINITE);  
  65.         if (tickets>0)  
  66.         {  
  67.             Sleep(1);  
  68.             cout<<"thread2 sell ticket :"<<tickets--<<endl;  
  69.         }  
  70.         else  
  71.             break;  
  72.         ReleaseMutex(hMutex);  
  73.     }  
  74.       
  75.     return 0;  
  76. }  
  77. //详解  
  78. HANDLE CreateMutex(  
  79.  LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针  
  80.  BOOL bInitialOwner, // 初始化互斥对象的所有者  
  81.  LPCTSTR lpName // 指向互斥对象名的指针  
  82. );  
  83. 参数   
  84. lpMutexAttributes   
  85. 指向一个SECURITY_ATTRIBUTES结构的指针,这个结构决定互斥体句柄是否被子进程继承。       
  86. bInitialOwner   
  87. 布尔类型,决定互斥体的创建者是否为拥有者   
  88. lpName   
  89. 指向互斥体名字字符串的指针。互斥体可以有名字。   
  90. 互斥体的好处是可以在进程间共享  
http://blog.csdn.net/goodai007/article/details/6976081
临界区例子:


[cpp]  view plain  copy
 print ?
  1.  // Global variable  
  2. CRITICAL_SECTION CriticalSection;   
  3.   
  4. void main()  
  5. {  
  6. ...  
  7.   
  8. // Initialize the critical section one time only.  
  9. if (!InitializeCriticalSectionAndSpinCount(&CriticalSection,   
  10. 0x80000400) )   
  11. return;  
  12. ...  
  13.   
  14. // Release resources used by the critical section object.  
  15. DeleteCriticalSection(&CriticalSection)  
  16. }  
  17.   
  18. DWORD WINAPI ThreadProc( LPVOID lpParameter )  
  19. {  
  20. ...  
  21.   
  22. // Request ownership of the critical section.  
  23. EnterCriticalSection(&CriticalSection);   
  24.   
  25. // Access the shared resource.  
  26.   
  27. // Release ownership of the critical section.  
  28. LeaveCriticalSection(&CriticalSection);  
  29.   
  30. ...  
  31. }  



更多例子在:
 VC下线程同步的三种方法(互斥、事件、临界区)
http://blog.csdn.net/pl2597758/article/details/2507790#

首选使用临界区对象,主要原因是使用简单。 
EnterCriticalSection()函数等候指定的危险区段对象的所有权。当调用的线程被允许所有权时,函数返回。 
EnterCriticalSection (),一个单独进程的线程可以使用一个危险区段对象作为相互-排除同步。 进程负责分配被一个危险区段对象使用的内存, 它藉由声明一个CRITICAL_SECTION类型 的变量实现。在使用一个危险区段之前,进程的一些线程必须调用 InitializeCriticalSection 函数设定对象的初值.
为了要使互斥的访问被共享的资源,每个线程调用EnterCriticalSection 或者 TryEnterCriticalSection 功能,在执行访问被保护资源的任何代码段之前,请求危险区段的所有权。 


[cpp]  view plain  copy
 print ?
  1. #include <windows.h>  
  2. #include <iostream>  
  3. using namespace std;  
  4. DWORD WINAPI Fun1Proc(LPVOID lpParameter);  
  5. DWORD WINAPI Fun2Proc(LPVOID lpParameter);  
  6. int tickets=100;  
  7. CRITICAL_SECTION g_csA;  
  8. CRITICAL_SECTION g_csB;  
  9. void main()  
  10. {  
  11.  HANDLE hThread1;  
  12.  HANDLE hThread2;  
  13.  hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);  
  14.  hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);  
  15.  CloseHandle(hThread1);  
  16.  CloseHandle(hThread2);  
  17.  InitializeCriticalSection(&g_csA);  
  18.  InitializeCriticalSection(&g_csB);  
  19.  Sleep(40000);  
  20.  DeleteCriticalSection(&g_csA);  
  21.  DeleteCriticalSection(&g_csB);  
  22. }  
  23. DWORD WINAPI Fun1Proc(LPVOID lpParameter)  
  24. {  
  25.  while (TRUE)  
  26.  {  
  27.   EnterCriticalSection(&g_csA);  
  28.   Sleep(1);  
  29.   //EnterCriticalSection(&g_csB);//临界区的同步和互锁  
  30.   if (tickets>0)  
  31.   {  
  32.    Sleep(1);  
  33.    cout<<"Thread1 sell ticket :"<<tickets--<<endl;  
  34.    //LeaveCriticalSection(&g_csB);  
  35.    LeaveCriticalSection(&g_csA);  
  36.   }  
  37.   else  
  38.   {  
  39.    //LeaveCriticalSection(&g_csB);  
  40.    LeaveCriticalSection(&g_csA);  
  41.    break;  
  42.   }  
  43.  }  
  44.  return 0;  
  45. }  
  46. DWORD WINAPI Fun2Proc(LPVOID lpParameter)  
  47. {  
  48.  while (TRUE)  
  49.  {  
  50.   EnterCriticalSection(&g_csB);  
  51.   Sleep(1);  
  52.   EnterCriticalSection(&g_csA);  
  53.   if (tickets>0)  
  54.   {  
  55.    Sleep(1);  
  56.    cout<<"Thread2 sell ticket :"<<tickets--<<endl;  
  57.    LeaveCriticalSection(&g_csA);  
  58.    LeaveCriticalSection(&g_csB);  
  59.   }  
  60.   else  
  61.   {  
  62.    LeaveCriticalSection(&g_csA);  
  63.    LeaveCriticalSection(&g_csB);  
  64.    break;  
  65.   }  
  66.  }  
  67.  return 0;  
  68. }  
  69.   
  70. --------------------------------------------------------------------------------  
  71.    
  72. 二、使用互斥对象  
  73. DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);   
  74. 如果时间是有信号状态返回WAIT_OBJECT_0,如果时间超过dwMilliseconds值但时间事件还是无信号状态则返回WAIT_TIMEOUT  
  75. WaitForSingleObject函数用来检测hHandle事件的信号状态,当函数的执行时间超过dwMilliseconds就返回,但如果参数dwMilliseconds为INFINITE时函数将直到相应时间事件变成有信号状态才返回,否则就一直等待下去,直到WaitForSingleObject有返回直才执行后面的代码。  
  76. #include <windows.h>  
  77. #include <iostream>  
  78. using namespace std;  
  79. DWORD WINAPI Fun1Proc(LPVOID lpParameter);  
  80. DWORD WINAPI Fun2Proc(LPVOID lpParameter);  
  81. int index =0;  
  82. int tickets=100;  
  83. HANDLE hMutex;  
  84. void main()  
  85. {  
  86.  HANDLE hThread1;  
  87.  HANDLE hThread2;  
  88.  //创建线程  
  89.  hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);  
  90.  hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);  
  91.  CloseHandle(hThread1);  
  92.  CloseHandle(hThread2);  
  93.  //**************************************************************  
  94.  //保证应用程序只有一个实例运行,创建一个命名的互斥对象.  
  95.  hMutex=CreateMutex(NULL,TRUE,LPCTSTR("tickets"));  
  96.  //创建时主线程拥有该互斥对象,互斥对象的线程ID为主线程的ID,同时将该互斥对象内部计数器置为1  
  97.  if (hMutex)  
  98.  {  
  99.   if (ERROR_ALREADY_EXISTS==GetLastError())  
  100.   {  
  101.    cout<<"only one instance can run!"<<endl;  
  102.    //Sleep(40000);  
  103.    return;  
  104.   }  
  105.  }  
  106.  //**************************************************************  
  107.  WaitForSingleObject(hMutex,INFINITE);  
  108.  //使用该函数请求互斥对象时,虽说该对象处于无信号状态,但因为请求的线程ID和该互斥对象所有者的线程ID是相同的.所以仍然可以请求到这个互斥对象,于是该互斥对象内部计数器加1,内部计数器的值为2. 意思是有两个等待动作  
  109.  ReleaseMutex(hMutex);//释放一次互斥对象,该互斥对象内部计数器的值递减1,操作系统不会将这个互斥对象变为已通知状态.  
  110.  ReleaseMutex(hMutex);//释放一次互斥对象,该互斥对象内部计数器的值为0,同时将该对象设置为已通知状态.  
  111.  //对于互斥对象来说,谁拥有谁释放  
  112.  Sleep(40000);  
  113. }  
  114. DWORD WINAPI Fun1Proc(LPVOID lpParameter)  
  115. {  
  116.  while (TRUE)  
  117.  {  
  118.   WaitForSingleObject(hMutex,INFINITE);//等待互斥对象有信号  
  119.   if (tickets>0)  
  120.   {  
  121.    Sleep(1);  
  122.    cout<<"thread1 sell ticket :"<<tickets--<<endl;  
  123.   }  
  124.   else  
  125.    break;  
  126.   ReleaseMutex(hMutex);//设置该互斥对象的线程ID为0,并且将该对象设置为有信号状态  
  127.  }  
  128.  return 0;  
  129. }  
  130. DWORD WINAPI Fun2Proc(LPVOID lpParameter)  
  131. {  
  132.  while (TRUE)  
  133.  {  
  134.   WaitForSingleObject(hMutex,INFINITE);  
  135.   if (tickets>0)  
  136.   {  
  137.    Sleep(1);  
  138.    cout<<"thread2 sell ticket :"<<tickets--<<endl;  
  139.   }  
  140.   else  
  141.    break;  
  142.   ReleaseMutex(hMutex);  
  143.  }  
  144.  return 0;  
  145. }  
  146.   
  147. --------------------------------------------------------------------------------  
  148.   
  149. 三、使用事件对象  
  150. HANDLE     CreateEvent(     
  151.         LPSECURITY_ATTRIBUTES     lpEventAttributes,           //     SD     
  152.         BOOL     bManualReset,                                                 //     reset     type     
  153.         BOOL     bInitialState,                                                     //     initial     state     
  154.         LPCTSTR     lpName                                                      //     object     name     
  155.     );     
  156.     该函数创建一个Event同步对象,并返回该对象的Handle     
  157.       
  158.     lpEventAttributes     一般为NULL     
  159.     bManualReset               创建的Event是自动复位还是人工复位     ,如果true,人工复位,     
  160.     一旦该Event被设置为有信号,则它一直会等到ResetEvent()API被调用时才会恢复     
  161.     为无信号.     如果为false,Event被设置为有信号,则当有一个wait到它的Thread时,     
  162.     该Event就会自动复位,变成无信号.     
  163.     bInitialState             初始状态,true,有信号,false无信号     
  164.     lpName                           Event对象名     
  165.       
  166.     一个Event被创建以后,可以用OpenEvent()API来获得它的Handle,用CloseHandle()     
  167.     来关闭它,用SetEvent()或PulseEvent()来设置它使其有信号,用ResetEvent()     
  168.     来使其无信号,用WaitForSingleObject()或WaitForMultipleObjects()来等待     
  169.     其变为有信号.     
  170.       
  171.     PulseEvent()是一个比较有意思的使用方法,正如这个API的名字,它使一个Event     
  172.     对象的状态发生一次脉冲变化,从无信号变成有信号再变成无信号,而整个操作是原子的.     
  173.     对自动复位的Event对象,它仅释放第一个等到该事件的thread(如果有),而对于     
  174.     人工复位的Event对象,它释放所有等待的thread.    
  175. #include <windows.h>  
  176. #include <iostream>  
  177. using namespace std;  
  178. DWORD WINAPI Fun1Proc(LPVOID lpParameter);  
  179. DWORD WINAPI Fun2Proc(LPVOID lpParameter);  
  180. int tickets=100;  
  181. HANDLE g_hEvent;  
  182. void main()  
  183. {  
  184.  HANDLE hThread1;  
  185.  HANDLE hThread2;  
  186.  //**************************************************  
  187.  //创建一个命名的自动重置事件内核对象  
  188.  g_hEvent=CreateEvent(NULL,FALSE,FALSE,LPCTSTR("tickets"));  
  189.  if (g_hEvent)  
  190.  {  
  191.   if (ERROR_ALREADY_EXISTS==GetLastError())  
  192.   {  
  193.    cout<<"only one instance can run!"<<endl;  
  194.    return;  
  195.   }  
  196.  }  
  197.  //**************************************************  
  198.  SetEvent(g_hEvent);  
  199.  //创建线程  
  200.  hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);  
  201.  hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);  
  202.  Sleep(40000);  
  203.  //关闭事件对象句柄  
  204.  CloseHandle(g_hEvent);  
  205. }  
  206. DWORD WINAPI Fun1Proc(LPVOID lpParameter)  
  207. {  
  208.  while (TRUE)  
  209.  {  
  210.   WaitForSingleObject(g_hEvent,INFINITE);  
  211.   //ResetEvent(g_hEvent);  
  212.   if (tickets>0)  
  213.   {  
  214.    Sleep(1);  
  215.    cout<<"thread1 sell ticket :"<<tickets--<<endl;  
  216.    SetEvent(g_hEvent);  
  217.   }  
  218.   else  
  219.   {  
  220.    SetEvent(g_hEvent);  
  221.    break;  
  222.   }  
  223.  }  
  224.  return 0;  
  225. }  
  226. DWORD WINAPI Fun2Proc(LPVOID lpParameter)  
  227. {  
  228.  while (TRUE)  
  229.  {  
  230.   WaitForSingleObject(g_hEvent,INFINITE);  
  231.   //ResetEvent(g_hEvent);  
  232.   if (tickets>0)  
  233.   {  
  234.    cout<<"Thread2 sell ticket :"<<tickets--<<endl;  
  235.    SetEvent(g_hEvent);  
  236.   }  
  237.   else  
  238.   {  
  239.    SetEvent(g_hEvent);  
  240.    break;  
  241.   }  
  242.  }  
  243.  return 0;  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
仿多线程的效果一般有2种办法:第一种是通过定时器;第二种是启动多线程,不同模式下启动函数不同,mfc与API与WIN32下面注意点也是有区别的! VC启动一个新线程的三种方法,有需要的朋友可以参考下。 第一种AfxBeginThread() 用AfxBeginThread()函数来创建一个新线程来执行任务,工作者线程的AfxBeginThread的原型如下: CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,   LPVOID lParam,   int nPriority = THREAD_PRIORITY_NORMAL,   UINT nStackSize = 0,   DWORD dwCreateFlags = 0,   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL   );//用于创建工作者线程 返回值: 成功时返回一个指向新线程线程对象的指针,否则NULL。 pfnThreadProc : 线程的入口函数,声明一定要如下: UINT MyThreadFunction(LPVOID pParam),不能设置为NULL; pParam : 传递入线程的参数,注意它的类型为:LPVOID,所以我们可以传递一个结构体入线程. nPriority : 线程的优先级,一般设置为 0 .让它和主线程具有共同的优先级. nStackSize : 指定新创建的线程的栈的大小.如果为 0,新创建的线程具有和主线程一样的大小的栈 dwCreateFlags : 指定创建线程以后,线程有怎么样的标志.可以指定两个值: CREATE_SUSPENDED : 线程创建以后,会处于挂起状态,直到调用:ResumeThread 0 : 创建线程后就开始运行. lpSecurityAttrs : 指向一个 SECURITY_ATTRIBUTES 的结构体,用它来标志新创建线程的安全性.如果为 NULL, 那么新创建的线程就具有和主线程一样的安全性. 如果要在线程内结束线程,可以在线程内调用 AfxEndThread. 一般直接用AfxBeginThread(ThreadProc,this); 示例: UINT myproc(LPVOID lParam){CITTDlg *pWnd = (CITTDlg *)lParam; //将窗口指针赋给无类型指针pWnd->KMeansSegment(); //要执行的函数return 1;}void CITTDlg::KMeansSegment(){// 主要处理函数在这里写}void CITTDlg::OnKMeansSegment() //按钮点击执行{AfxBeginThread(myproc, (LPVOID)this);//启动新的线程} 注意,工作者线程的函数必须是全局函数或静态成员函数,不能是普通的成员函数。 第二种CreateThread()函数原型为:HANDLECreateThread( NULL, // 没有安全描述符 0, // 默认线程栈的大小 MyThreadProc, // 线程函数指针,即函数名 (LPVOID)&n, // 传递参数 NULL, // 没有附加属性 NULL // 不需要获得线程号码 ); CreatThread,它返回的是一个句柄;如果不需要再监视线程,则用CloseHandle()关闭线程句柄。 线程的函数必须定义为: DWORD WINAPI MyThreadProc(LPVOID pParameter); 下面演示多线程操作控件,点击一个Button然后运行一个线程,将字符串显示在CEdit控件里面; 示例: .h头文件struct hS {CString Tmp;CTestDlg *hWnd; };//定义全局结构体,用来传递自定义消息DWORD WINAPI ThreadProc(LPVOIDlpParam);//线程函数声明,全局函数public: CString chtmp; struct hS *hTmp;protected: HANDLE m_hThread;//线程句柄 CEdit m_Edit;.cpp实现文件//线程执行函数DWORD WINAPI ThreadProc(LPVOID lpParam){//在这里写处理函数struct hS *Tmp2;Tmp2 = (hS*)lpParam;// 操作: Tmp2->hWnd->m_Edit.SetWindowText( (LPTSTR)Tmp2->Tmp );}void CTestDlg::OnBnClickedButton1(){ hTmp->Tmp = chtmp; hTmp->hWnd = this;//关键是把this指针传进去 m_hThread =CreateThread(NULL,0,ThreadProc,hTmp,0,NULL);//创建新线程 CloseHandle(m_hThread );} 用CreateThread()函数创建线程将返回一个线程句柄,通过该句柄你可以控制和操作该线程,当你不用时可以一创建该线程后就关闭该句柄,有专门的函CloseHandle()。关闭句柄不代表关闭线程,只是你不能在外部控制该线程(比如,提前结束,更改优先级等)。在线程结束后,系统将自动清理线程资源,但并不自动关闭该句柄,所以线程结束后要记得关闭该句柄。 第三种_beginthread() 函数原型为:intptr_t _beginthread( void( *start_address )( void * ), //指向新线程调用的函数的起始地址 unsigned stack_size, //堆栈大小,设置0为系统默认值 void *arglist //传递给线程函数的参数,没有则为NULL ); 返回值: 假如成功,函数将会返回一个新线程的句柄,用户可以像这样声明一个句柄变量存储返回值:   HANDLE hStdOut = _beginthread( CheckKey, 0, NULL )。如果失败_beginthread将返回-1。所在库文件: #include 线程函数的定义: 对于_beginthread()创建的线程,其线程函数定义为: void ThreadPro(void * pArguments ); _beginthreadex()为_beginthread()的升级版。 总结:AfxBeginThread是MFC的全局函数,是对CreateThread的封装。 CreateThread是Win32 API函数,AfxBeginThread最终要调到CreateThread。而_beginthread是C的运行库函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值