VC信号量和线程的用法

Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 VC 信号量和线程的用法

20090904 下午 08:23

先举个例:
CSemaphore semaphore(1,2);

UINT BoxA(LPVOID pParam)
{
WaitForSingleObject(semaphore.m_hObject,INFINITE);
/*
AfxMessageBox("BoxA");
*/
ReleaseSemaphore(semaphore.m_hObject,1,NULL);
return 0;
}
UINT BoxB(LPVOID pParam)
{
WaitForSingleObject(semaphore.m_hObject,INFINITE);
/*
AfxMessageBox("BoxB");
*/
ReleaseSemaphore(semaphore.m_hObject,1,NULL);
return 0;

}
UINT BoxC(LPVOID pParam)
{
WaitForSingleObject(semaphore.m_hObject,INFINITE);
/*
AfxMessageBox("BoxC");
*/
ReleaseSemaphore(semaphore.m_hObject,1,NULL);
return 0;

}

......

void CMyDlg::OnStart()
{
CWinThread *pWriteA=AfxBeginThread(BoxA, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
pWriteA->ResumeThread();

CWinThread *pWriteB=AfxBeginThread(BoxB, this,, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
pWriteB->ResumeThread();

CWinThread *pWriteC=AfxBeginThread(BoxC, this,, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
pWriteC->ResumeThread();
}
这段示例程序主要有三部分:信号量的创建、线程定义、线程调用。CSemaphore semaphore(1,2)1为信号量的初始值(即此时只允许1个线程能拥有此信号量,当然这个值在0

最大值之间可以增加或减小),2为信号量的最大值(也就是最大线程访问数目),比如此处设为2,表示此信号量最多只允许俩个线程同时拥有它,其它线程想要获得此信号量的

话只能等待这两个线程释放此信号量,或调用ReleaseSemaphore(semaphore.m_hObject,1,NULL)函数来增加信号量的值。WaitForSingleObject(semaphore.m_hObject,INFINITE)

数调用后信号量的值自动减1,当减到0时,其它线程就不能再利用此信号量了。ReleaseSemaphore(semaphore.m_hObject,1,NULL)函数使信号量的值加1,当加到最大值时,信号量

的值不再增大,此函数成功时返回1,调用失败时返回0,当信号量计数器已达到最大值时再调用此函数就会调用失败,或者此函数的第三个参数+此时信号量的值>最大值时也会调

用失败,调用失败的意思是忽略此函数,程序继续运行。

关于将类的成员函数作为线程:
以上提到的线程,都是通过标准UINT func(LPVOID pParam)形式来定义,但是有的时候成员函数需要等待信号量或者成员函数的执行代码比较大时,不为其分配其它的线程的话程序的效率将会受到影响。将某 类的成员函数单独作为一条线程来执行最常用的办法是将成员函数申明为静态,即static UINT func(LPVOID pParam)
其它的处理方法和普通线程差不多,但是静态成员函数只能访问类的静态成员,想要访问非静态成员的话可以将this指针传递给pParam参数来实现,举例如下:

文件1
CSemaphore semaphore(0,1);
class CVideoNetDlg:public CDialog
{
public:
CViewDlg *viewdlg;
......
}

UINT CVideoNetDlg::Thread_OpenViewDlg(LPVOID param)
{
WaitForSingleObject(semaphore.m_hObject,300);//
信号量减1
CVideoNetDlg *dlg = (CVideoNetDlg*)param;
dlg->viewdlg->DoModal();
return NULL;
}  

void CVideoNetDlg::OnView()
{
dcontrol.SendViewApply();
CWinThread *pWriteC=AfxBeginThread(Thread_OpenViewDlg, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
pWriteC->ResumeThread();
}

文件2
case MESG_VIEW:
{
memcpy(CViewDlg::clientdata,&data[1],length-1);
ReleaseSemaphore(semaphore.m_hObject,1,NULL);
}

此段程序的目的是在处理函数OnView()时,获得信号量semaphore后再调用CviewDlg类的模式对话框(其实是这样的,点击某个菜 单弹出对话框,但是这个对话框初始化时必须要利用数组CViewDlg::clientdata的数据,而这个数组是在点击这个菜单时发送某代码到远程 机,再从远程机返回的数据得到赋值的。)
实现方法就是建立一个二值信号量,并置其初始值为0,这样在点击菜单时线程由于得不到信号量一直处于等待状态,模式对话框就不会被调用,直到文件2中的数 组得到赋值后,信号量释放(即增1)这个线程获得了信号量就继续往下运行,调用对话框。这样一来,就保证了对话框使用数组 CViewDlg::clientdata来初始化。

另外,此线程Thread_OpenViewDlg(LPVOID param)为类CVideoNetDlg的静态成员函数,但是很显然它使用了类CVideoNetDlg的非静态公有成员viewdlg,这就是利用 this指针在***.OnView()函数中将CVideoNetDlg的对象***传递给了param参数,在通过 (CVideoNetDlg*)paramLPVOID类型转换为CVideoNetDlg,执行CVideoNetDlg *dlgdlg已经成了CVideoNetDlg的对象并获得了***的指针,这样就可以调用其成员viewdlg了。

最后,为什么将信号量和线程放在一起来分析,其实信号量就是线程编程,自己一个信号量也是很简单的事情:分配一个额外的线程,在这个线程中用 while循环来检测你自定义的信号量的变化,由于while在单独的线程中执行,它不会影响主线程运行的。vc专门用这种机制只不过是来简化编程罢了 (个人愚见...)。

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25897606/viewspace-704805/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/25897606/viewspace-704805/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值