There can be no Triumph without Loss,No Victory without Suffering,No Freedom without Sacrifice.
All you have to decide is what to do with the time that is given to you.
Get busy Living, or Get busy Dying?
  首页 | 留言给我 | 订阅 Rss | CLI | 黄白之恋 Posts:158   Hits: 2066506    Comments: 170    
 日历归档
<<  <  2020 - 04  >  >>
SuMoTuWeThFrSa
   1234
567891011
12131415161718
19202122232425
2627282930
 About Me
 Name: ZhangSichu
 Sex: Male
 Age: 32
 Email: ZhangSichu@gmail.com
 MSN: ZhangSichu@hotmail.com
 Home: ZhangSichu.com
 WeiBo: weibo.com/zhangsichu
 个人推荐
 分类归档
  ·C++/C(5)  RSS
  ·软件工程(1)  RSS
  ·杂事/随感(26)  RSS
  ·.Net/Java(30)  RSS
  ·面向对象程序设计(5)  RSS
  ·汇编/破解(0)  RSS
  ·平面设计(3)  RSS
  ·SQL(5)  RSS
  ·COM/COM+(2)  RSS
  ·Web开发(81)  RSS
 My Friends
Back Forward Refresh Home 2020年4月5日 星期日 RSS CLI Mine Sweeper. In Javascript.

  用信号量控制线程
字体大小 [ ]

开发环境:VS7,Windows XP

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

控制信号量几个主要的函数:
WaitForSingleObject();//等待信号量有效
CreatSemaphore();//申请信号量
OpenSemaphore();//打开信号量
ReleaseSemaphore();//释放信号量

下面来看看控制多线程要用到的东西:
HANDLE ptrSpdUpDown;
HANDLE ptrUpDownDraw;
HANDLE ptrDrawSpd; //申请指向信号量的句柄
  ptrSpdUpDown = ::CreateSemaphore(NULL, 0, 1, NULL);
  ptrUpDownDraw = ::CreateSemaphore(NULL, 0, 1, NULL);
  ptrDrawSpd = ::CreateSemaphore(NULL, 1, 1, NULL);//实例化三个信号量

bOnOff=true;//线程状态控制量 开启三个线程
    m_tWriteSpeed=AfxBeginThread(WriteSpeed,
      &m_sWriteSpeed,
      THREAD_PRIORITY_NORMAL,
      0,
      CREATE_SUSPENDED);
    m_tWriteSpeed->ResumeThread();
    m_tWriteUpDown=AfxBeginThread(WriteUpDown,
      &m_sWriteUpDown,
      THREAD_PRIORITY_NORMAL,
      0,
      CREATE_SUSPENDED);
    m_tWriteUpDown->ResumeThread();
    m_tDrawWindow=AfxBeginThread(DrawWindow,
      &m_sDrawWindow,
      THREAD_PRIORITY_NORMAL,
      0,
      CREATE_SUSPENDED);
    m_tDrawWindow->ResumeThread();

//三个线程函数
UINT WriteSpeed(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CString sMe;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    WaitForSingleObject(ptrDrawSpd,INFINITE);
    ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe+"已经接到信号");
    ::Sleep(1000);
    srand((int)time(0));//种种子数
    iSpeed=iUp+iDown+rand();
    ReleaseSemaphore(ptrSpdUpDown,1,NULL);
    sTr.Format("%d",iNo);
    sMe.Format("%d",iSpeed);
    ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe);
    iNo++;
  }
  return 0;
}
UINT WriteUpDown(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CString sMe;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    WaitForSingleObject(ptrSpdUpDown,INFINITE);
    ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe+"已经接到信号");
    ::Sleep(1000);
    srand((int)time(0));//种种子数
    iUp=iSpeed-rand();
    iDown=iSpeed+rand();
    ReleaseSemaphore(ptrUpDownDraw,1,NULL);
    sTr.Format("%d",iNo);
    sMe.Format("%d",iUp);
    ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe);
    iNo++;
  }
  return 0;
}
UINT DrawWindow(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    WaitForSingleObject(ptrUpDownDraw,INFINITE);
    ptr->SetWindowText("线程DrawWindow正在运行"+sTr+"已经接到信号");
    ::Sleep(1000);
    sTr.Format("%d",iNo);
    ptr->SetWindowText("线程DrawWindow正在运行"+sTr);
    iNo++;
    ReleaseSemaphore(ptrDrawSpd,1,NULL);
  }
  return 0;
}
上面的方法是先申请信号量的句柄然后再实例化信号量 下面这种方法是直接申请信号量 两种方法基本相同
CSemaphore ptrSpdUpDown(0, 1);
CSemaphore ptrUpDownDraw(0, 1);
CSemaphore ptrDrawSpd(1, 1);//#include <atlsync.h>注意在stdafx.h手动包含这个文件
在各个线程函数中不用WaitForSingleObject了要使用Lock()UnLock();
下面是使用CSemaphore后在各个线程函数中使用Lock()UnLock()替换掉WaitForSingleObject的结果
UINT WriteSpeed(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CString sMe;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    ptrDrawSpd.Lock();
    ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe+"已经接到信号");
    ::Sleep(1000);
    srand((int)time(0));//种种子数
    iSpeed=iUp+iDown+rand();
    ReleaseSemaphore(ptrSpdUpDown,1,NULL);
    ptrSpdUpDown.Unlock();
    sTr.Format("%d",iNo);
    sMe.Format("%d",iSpeed);
    ptr->SetWindowText("线程WriteSpeed正在运行"+sTr+"---Speed:"+sMe);
    iNo++;
  }
  return 0;
}
UINT WriteUpDown(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CString sMe;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    ptrSpdUpDown.Lock();
    ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe+"已经接到信号");
    ::Sleep(1000);
    srand((int)time(0));//种种子数
    iUp=iSpeed-rand();
    iDown=iSpeed+rand();
    ReleaseSemaphore(ptrUpDownDraw,1,NULL);
    ptrUpDownDraw.Unlock();
    sTr.Format("%d",iNo);
    sMe.Format("%d",iUp);
    ptr->SetWindowText("线程WriteUpDown正在运行"+sTr+"---Up:"+sMe);
    iNo++;
  }
  return 0;
}
UINT DrawWindow(LPVOID p)
{
  int iNo=1;
  CString sTr;
  CEdit *ptr=(CEdit *)p;
  while(bOnOff)
  {
    ptrUpDownDraw.Lock();
    ptr->SetWindowText("线程DrawWindow正在运行"+sTr+"已经接到信号");
    ::Sleep(1000);
    sTr.Format("%d",iNo);
    ptr->SetWindowText("线程DrawWindow正在运行"+sTr);
    iNo++;
    ReleaseSemaphore(ptrDrawSpd,1,NULL);
    ptrDrawSpd.Unlock();
}
  return 0;
}
推荐使用第一种方法,第一种方法只声明了句柄,当信号量实例化的时候句柄才指向三个信号量。所以更加支持多态。

程序初始化
Click to Open in New Window

程序运行中
Click to Open in New Window


开发环境:VS7,Windows XP
  Posted @ 2/11/2005 12:12:35 AM | Hits (44287) | Comments (3

  Comment
 #re:用信号量控制线程  11/16/2006 1:16:33 PM  point
很普通的东西啊。
 #re:用信号量控制线程  9/17/2005 3:29:16 PM  淡如云烟
现在才知道,什么信号量了!
呵呵
 #re:用信号量控制线程  2/13/2005 1:38:38 AM  BILL
什么东东,俺连标题都木有看明北:(
  Post Comment
标题 *
作者 *
密码 记住我
评论 *
    


Stable in Firefox 1.5 2.0Stable in IE6 IE7Stable in MozillaStable in Netscape
ZhangSichu.com V0.1.7507
Powered By ZhangSichu
Copyright © ZhangSichu
Download ZhangSichu.com source code. Download source code