[MFC]同步对象——CEvent事件,CMutex互斥量

来源:互联网 发布:知豆属于哪个品牌 编辑:程序博客网 时间:2024/05/17 22:51

实例——CEvent事件

头文件关键代码:
// MFCEventDlg.h : 头文件#pragma once#define WM_MSG WM_USER+1typedef struct THREAD_PARAM{HWND hWnd;int nData;CEvent* pEvent;}_THREAD_PARAM;UINT ThreadFun(LPVOID pParam);class CMFCEventDlg : public CDialogEx{//...//定义的成员变量THREAD_PARAM mThreadParam;CWinThread* pThread;// ...};
cpp文件关键代码:
// MFCEventDlg.cpp : 实现文件CMFCEventDlg::CMFCEventDlg(CWnd* pParent /*=NULL*/): CDialogEx(CMFCEventDlg::IDD, pParent){m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);pThread=NULL;mThreadParam.nData=0;mThreadParam.pEvent=new CEvent(TRUE,FALSE,L"eventDlg");//new CEvent(BOOL bInitiallyOwn = FALSE,BOOL bManualReset = FALSE,LPCTSTR lpszName = NULL,);  //bInitiallyOwn:如果为TRUE,CMultilock或CSingleLock对象的线程可用;如果为FALSE,所有要访问资源的线程必须等待。//bManualReset:如果为TRUE,指定事件是一个手工事件,否则事件是一个自动事件。 //lpszName:CEvent事件的名字//要访问或释放一个CEvent对象,可建立一个CSingleLock或CMultiLock对象并调用其Lock和Unlock成员函数。要将CEvent对象的状态改为已标记(无须等待的线程),可调用SetEvent或PulseEvent。要设置一个CEvent对象为无标记(必须等待的线程),可调用ResetEvent。}CMFCEventDlg::~CMFCEventDlg(){if (pThread){mThreadParam.pEvent->SetEvent();//设置事件WaitForSingleObject(pThread->m_hThread,INFINITE);//等待线程结束delete pThread;pThread=NULL;}if (mThreadParam.pEvent){delete mThreadParam.pEvent;mThreadParam.pEvent=NULL;}}BEGIN_MESSAGE_MAP(CMFCEventDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON_START, &CMFCEventDlg::OnBnClickedButtonStart)ON_BN_CLICKED(IDC_BUTTON_STOP, &CMFCEventDlg::OnBnClickedButtonStop)ON_MESSAGE(WM_MSG,&CMFCEventDlg::OnMsgFun)END_MESSAGE_MAP()//WM_MSG消息函数LRESULT CMFCEventDlg::OnMsgFun(WPARAM wParam,LPARAM lParam){SetDlgItemInt(IDC_EDIT_DATA,mThreadParam.nData);return 0;}//启动线程按钮事件函数void CMFCEventDlg::OnBnClickedButtonStart(){ if (pThread){AfxMessageBox(_T("线程已经启动。"));return;}mThreadParam.hWnd=m_hWnd;mThreadParam.pEvent->ResetEvent();//重置事件pThread=AfxBeginThread(ThreadFun,&mThreadParam,THREAD_PRIORITY_ABOVE_NORMAL,0,CREATE_SUSPENDED);pThread->m_bAutoDelete=FALSE;//线程结束后不自动消失pThread->ResumeThread();//调用这个函数以使被SuspendThread成员函数所挂起的线程恢复执行,或者使用CREATE_SUSPENDED标志创建的线程恢复执行。当前线程的挂起计数被减小1。如果挂起计数被减小到0,线程将恢复执行;否则线程继续被挂起。}//停止线程按钮事件函数void CMFCEventDlg::OnBnClickedButtonStop(){ if (pThread==NULL){AfxMessageBox(_T("线程已经停止。"));return;}mThreadParam.pEvent->SetEvent();::WaitForSingleObject(pThread->m_hThread,INFINITE);delete pThread;pThread=NULL;}//线程函数UINT ThreadFun(LPVOID pParam){THREAD_PARAM* pThread=(THREAD_PARAM*)pParam;while(TRUE){if (::WaitForSingleObject(pThread->pEvent->m_hObject,0) == WAIT_OBJECT_0){break;}Sleep(100);pThread->nData++;::PostMessage(pThread->hWnd,WM_MSG,0,0);} return 0;}

效果图:

实例——CMutex互斥量

互斥量与临界区很相似,但是使用时相对复杂一些,它不仅可以在同一应用程序的线程间实现同步,还可以在不同的进程间实现同步,从而实现资源的安全共享。互斥量与CMutex类的对象相对应,使用互斥对象时,必须创建一个CSingleLockCMultiLock对象,用于实际的访问控制,该对象的Lock()函数用于占有互斥,Unlock()函数用于释放互斥。

头文件关键代码:
// MFCMutaxDlg.h : 头文件 #pragma once#define  WM_MSG WM_USER+1typedef struct THREAD_PARAM{HWND hWnd;int nData;CMutex* pMutex;}_THREAD_PARAM;UINT ThreadFun1(LPVOID pParam);UINT ThreadFun2(LPVOID pParam);

cpp文件关键代码:
// MFCMutaxDlg.cpp : 实现文件CMFCMutaxDlg::CMFCMutaxDlg(CWnd* pParent /*=NULL*/): CDialogEx(CMFCMutaxDlg::IDD, pParent){m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);///定义的成员变量// THREAD_PARAM mThreadParam;// CWinThread* pThread1;// CWinThread* pThread2;pThread1=NULL;pThread2=NULL;mThreadParam.nData=0;mThreadParam.pMutex=new CMutex();//CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );/*bInitiallyOwn 指定是否创建了CMutex对象的线程最初拥有由哑程控制资源的访问权。  lpszNameCMutex 对象的名称。若其它的哑程由同样的名称,那么必须提供lpszName,以便对象能够通过进程边界。若该值为NULL,那么哑程将没有命名。若该名称匹配已经存在的哑程,那么构造函数将创建一个参考哑程名称的新CMutex对象。若该名称匹配已存在的不是哑程的同步对象,那么构造过程将失败。  lpsaAttribute 哑程对象的安全性。如果需要该结构的完整描述,请参阅“Win32程序员参考”中的SECURITY_ATTRIBUTES。  说明:构造一个命名的或未命名的CMutex对象,若要访问或释放CMutex对象,那么请创建CMultiLock或CSingleLock 对象,并调用Lock或Unlock成员函数。若CMutex对象被独占使用,那么调用Unlock成员函数释放它。 */}CMFCMutaxDlg::~CMFCMutaxDlg(){if (pThread1){::WaitForSingleObject(pThread1->m_hThread,INFINITE);delete pThread1;pThread1=NULL;}if (pThread2){::WaitForSingleObject(pThread2->m_hThread,INFINITE);delete pThread2;pThread2=NULL;}if (mThreadParam.pMutex){delete mThreadParam.pMutex;mThreadParam.pMutex=NULL;}}BEGIN_MESSAGE_MAP(CMFCMutaxDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON_START, &CMFCMutaxDlg::OnBnClickedButtonStart)ON_MESSAGE(WM_MSG,&CMFCMutaxDlg::OnMsgFun)END_MESSAGE_MAP()//WM_MSG消息函数,其格式是:LRESULT Fun(WPARAM wParam,LPARAM lParam)LRESULT CMFCMutaxDlg::OnMsgFun(WPARAM wParam,LPARAM lParam){SetDlgItemInt(IDC_EDIT_DATA,mThreadParam.nData);return 0;}//开始线程按钮事件void CMFCMutaxDlg::OnBnClickedButtonStart(){if (pThread1 !=NULL)//只执行一次ThreadFun,去掉中间3行{AfxMessageBox(_T("线程已经启动。"));::WaitForSingleObject(pThread1->m_hThread,INFINITE);delete pThread1;pThread1=NULL;return;} if (pThread2)//可以执行多次ThreadFun{DWORD exitCode=0;if (::GetExitCodeThread(pThread2->m_hThread,&exitCode)){if (exitCode == STILL_ACTIVE){AfxMessageBox(_T("线程2已经启动。"));return ;}else{delete pThread2;pThread2=NULL;}}}mThreadParam.hWnd=m_hWnd;pThread1=AfxBeginThread(ThreadFun1,&mThreadParam,THREAD_PRIORITY_ABOVE_NORMAL,0,CREATE_SUSPENDED);pThread2=AfxBeginThread(ThreadFun2,&mThreadParam,THREAD_PRIORITY_ABOVE_NORMAL,0,CREATE_SUSPENDED);pThread1->m_bAutoDelete=FALSE;pThread2->m_bAutoDelete=FALSE;pThread1->ResumeThread();pThread2->ResumeThread();}//线程函数1UINT ThreadFun1(LPVOID pParam){THREAD_PARAM* pThreadParam=(THREAD_PARAM*)pParam;CSingleLock sigleLock(pThreadParam->pMutex,TRUE);/*CSingleLock( CSyncObject* pObject, BOOL bInitialLock = FALSE );参数: pObject 指向要被访问的同步对象。不能是NULL。  bInitialLock 指示是否要在最初尝试访问所提供的对象。   此成员函数用来构造一个CSingleLock对象。通常是从被控制资源的一个访问成员函数中来调用这个函数。 */if (sigleLock.IsLocked())//使用前要加锁{for (int i=0;i<10;i++){pThreadParam->nData++;::PostMessage(pThreadParam->hWnd,WM_MSG,0,0);Sleep(200);}sigleLock.Unlock();//使用后要解锁}return 0;}//线程函数2UINT ThreadFun2(LPVOID pParam){THREAD_PARAM* pThreadParam=(THREAD_PARAM*)pParam;CSingleLock singleLock(pThreadParam->pMutex);singleLock.Lock();if (singleLock.IsLocked()){for (int i=0;i<10;i++){pThreadParam->nData--;::PostMessage(pThreadParam->hWnd,WM_MSG,0,0);Sleep(100);}singleLock.Unlock();}return 0;}

效果图: