windows C++ 用信号量控制线程

来源:互联网 发布:大学生旅游的地方知乎 编辑:程序博客网 时间:2024/05/19 13:44

转载自:http://www.iteye.com/topic/348145

很好的控制线程,让线程互斥,互相协调工作,共享数据,这个问题有很多种解决办法,不过我个人觉得使用信号量控制线程特别方便。会想到用多线程控制程序,是由于上学期我们要做一个控制电机转速的课程设计,开始编写的程序都是一个线程控制的。后来课程设计结束了,一次在看多线程的演示程序的时候突然想到,原来的那个电机控制程序完全可以写成多线程,可是由于课程设计结束了,没有硬件供你调试,就自己写了个多线程的练习程序。
控制信号量几个主要的函数:

Cpp代码  收藏代码
  1. WaitForSingleObject();//等待信号量有效  
  2. CreatSemaphore();//申请信号量  
  3. OpenSemaphore();//打开信号量  
  4. ReleaseSemaphore();//释放信号量  

 
下面来看看控制多线程要用到的东西:

Cpp代码  收藏代码
  1. HANDLE ptrSpdUpDown;  
  2. HANDLE ptrUpDownDraw;  
  3. HANDLE ptrDrawSpd; //申请指向信号量的句柄  
  4.   ptrSpdUpDown = ::CreateSemaphore(NULL, 0, 1, NULL);  
  5.   ptrUpDownDraw = ::CreateSemaphore(NULL, 0, 1, NULL);  
  6.   ptrDrawSpd = ::CreateSemaphore(NULL, 1, 1, NULL);//实例化三个信号量  
  7.   
  8. bOnOff=true;//线程状态控制量 开启三个线程  
  9.     m_tWriteSpeed=AfxBeginThread(WriteSpeed,  
  10.       &m_sWriteSpeed,  
  11.       THREAD_PRIORITY_NORMAL,  
  12.       0,  
  13.       CREATE_SUSPENDED);  
  14.     m_tWriteSpeed->ResumeThread();  
  15.     m_tWriteUpDown=AfxBeginThread(WriteUpDown,  
  16.       &m_sWriteUpDown,  
  17.       THREAD_PRIORITY_NORMAL,  
  18.       0,  
  19.       CREATE_SUSPENDED);  
  20.     m_tWriteUpDown->ResumeThread();  
  21.     m_tDrawWindow=AfxBeginThread(DrawWindow,  
  22.       &m_sDrawWindow,  
  23.       THREAD_PRIORITY_NORMAL,  
  24.       0,  
  25.       CREATE_SUSPENDED);  
  26.     m_tDrawWindow->ResumeThread();  
  27.   
  28. //三个线程函数  
  29. UINT WriteSpeed(LPVOID p)  
  30. {  
  31.   int iNo=1;  
  32.   CString sTr;  
  33.   CString sMe;  
  34.   CEdit *ptr=(CEdit *)p;  
  35.   while(bOnOff)  
  36.   {  
  37.     WaitForSingleObject(ptrDrawSpd,INFINITE);  
  38.     ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe+"已经接到信号");  
  39.     ::Sleep(1000);  
  40.     srand((int)time(0));//种种子数  
  41.     iSpeed=iUp+iDown+rand();  
  42.     ReleaseSemaphore(ptrSpdUpDown,1,NULL);  
  43.     sTr.Format("%d",iNo);  
  44.     sMe.Format("%d",iSpeed);  
  45.     ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe);  
  46.     iNo++;  
  47.   }  
  48.   return 0;  
  49. }  
  50. UINT WriteUpDown(LPVOID p)  
  51. {  
  52.   int iNo=1;  
  53.   CString sTr;  
  54.   CString sMe;  
  55.   CEdit *ptr=(CEdit *)p;  
  56.   while(bOnOff)  
  57.   {  
  58.     WaitForSingleObject(ptrSpdUpDown,INFINITE);  
  59.     ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe+"已经接到信号");  
  60.     ::Sleep(1000);  
  61.     srand((int)time(0));//种种子数  
  62.     iUp=iSpeed-rand();  
  63.     iDown=iSpeed+rand();  
  64.     ReleaseSemaphore(ptrUpDownDraw,1,NULL);  
  65.     sTr.Format("%d",iNo);  
  66.     sMe.Format("%d",iUp);  
  67.     ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe);  
  68.     iNo++;  
  69.   }  
  70.   return 0;  
  71. }  
  72. UINT DrawWindow(LPVOID p)  
  73. {  
  74.   int iNo=1;  
  75.   CString sTr;  
  76.   CEdit *ptr=(CEdit *)p;  
  77.   while(bOnOff)  
  78.   {  
  79.     WaitForSingleObject(ptrUpDownDraw,INFINITE);  
  80.     ptr->SetWindowText("线程DrawWindow正在运行"+sTr+"已经接到信号");  
  81.     ::Sleep(1000);  
  82.     sTr.Format("%d",iNo);  
  83.     ptr->SetWindowText("线程DrawWindow正在运行"+sTr);  
  84.     iNo++;  
  85.     ReleaseSemaphore(ptrDrawSpd,1,NULL);  
  86.   }  
  87.   return 0;  
  88. }  

 

上面的方法是先申请信号量的句柄然后再实例化信号量 下面这种方法是直接申请信号量 两种方法基本相同

Cpp代码  收藏代码
  1. CSemaphore ptrSpdUpDown(0, 1);  
  2. CSemaphore ptrUpDownDraw(0, 1);  
  3. CSemaphore ptrDrawSpd(1, 1);//#include <atlsync.h>注意在stdafx.h手动包含这个文件  

 在各个线程函数中不用WaitForSingleObject了要使用Lock()UnLock();
下面是使用CSemaphore后在各个线程函数中使用Lock()UnLock()替换掉WaitForSingleObject的结果

Cpp代码  收藏代码
  1. UINT WriteSpeed(LPVOID p)  
  2. {  
  3.   int iNo=1;  
  4.   CString sTr;  
  5.   CString sMe;  
  6.   CEdit *ptr=(CEdit *)p;  
  7.   while(bOnOff)  
  8.   {  
  9.     <strong>ptrDrawSpd.Lock();</strong>   
  10.     ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe+"已经接到信号");  
  11.     ::Sleep(1000);  
  12.     srand((int)time(0));//种种子数  
  13.     iSpeed=iUp+iDown+rand();  
  14.     ReleaseSemaphore(ptrSpdUpDown,1,NULL);  
  15.     <strong>ptrSpdUpDown.Unlock();</strong>  
  16.     sTr.Format("%d",iNo);  
  17.     sMe.Format("%d",iSpeed);  
  18.     ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe);  
  19.     iNo++;  
  20.   }  
  21.   return 0;  
  22. }  
  23. UINT WriteUpDown(LPVOID p)  
  24. {  
  25.   int iNo=1;  
  26.   CString sTr;  
  27.   CString sMe;  
  28.   CEdit *ptr=(CEdit *)p;  
  29.   while(bOnOff)  
  30.   {  
  31.     <strong>ptrSpdUpDown.Lock();</strong>  
  32.     ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe+"已经接到信号");  
  33.     ::Sleep(1000);  
  34.     srand((int)time(0));//种种子数  
  35.     iUp=iSpeed-rand();  
  36.     iDown=iSpeed+rand();  
  37.     ReleaseSemaphore(ptrUpDownDraw,1,NULL);  
  38.     <strong>ptrUpDownDraw.Unlock();</strong>  
  39.     sTr.Format("%d",iNo);  
  40.     sMe.Format("%d",iUp);  
  41.     ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe);  
  42.     iNo++;  
  43.   }  
  44.   return 0;  
  45. }  
  46. UINT DrawWindow(LPVOID p)  
  47. {  
  48.   int iNo=1;  
  49.   CString sTr;  
  50.   CEdit *ptr=(CEdit *)p;  
  51.   while(bOnOff)  
  52.   {  
  53.     <strong>ptrUpDownDraw.Lock();</strong>  
  54.     ptr->SetWindowText("线程DrawWindow正在运行"+sTr+"已经接到信号");  
  55.     ::Sleep(1000);  
  56.     sTr.Format("%d",iNo);  
  57.     ptr->SetWindowText("线程DrawWindow正在运行"+sTr);  
  58.     iNo++;  
  59.     ReleaseSemaphore(ptrDrawSpd,1,NULL);  
  60.     <strong>ptrDrawSpd.Unlock();</strong>  
  61. }  
  62.   return 0;  
  63. }  

 推荐使用第一种方法,第一种方法只声明了句柄,当信号量实例化的时候句柄才指向三个信号量。所以更加支持多态。

程序初始化
Click to Open in New Window

程序运行中
Click to Open in New Window

0 0
原创粉丝点击