频道直达 - 专题 - 新闻 - 技巧 - 组网 - 开发 - 安全 - web编程 - 图像 - 操作系统 - 数据库 - 教育 - 旅游 - 健康 - 时尚 - 驱动 - 软件 - 游戏 - 多媒体 - ERP - 讨论组

深入浅出Win32多线程设计之MFC的多线程

来源: 作者: 出处:巧巧读书 2007-12-16 进入讨论组
引用:http://www.qqread.com/vc/t202232200.html

  2.线程间通信

  MFC中定义了继承自CSyncObject类的CCriticalSection 、CCEvent、CMutex、CSemaphore类封装和简化了WIN32 API所提供的临界区、事件、互斥和信号量。使用这些同步机制,必须包含"Afxmt.h"头文件。下图给出了类的继承关系:

深入浅出Win32多线程设计之MFC的多线程(图二)

  作为CSyncObject类的继承类,我们仅仅使用基类CSyncObject的接口函数就可以方便、统一的操作CCriticalSection 、CCEvent、CMutex、CSemaphore类,下面是CSyncObject类的原型:

class CSyncObject : public CObject
{
 DECLARE_DYNAMIC(CSyncObject)

 // Constructor
 public:
  CSyncObject(LPCTSTR pstrName);

  // Attributes
 public:
  operator HANDLE() const;
  HANDLE m_hObject;

  // Operations
  virtual BOOL Lock(DWORD dwTimeout = INFINITE);
  virtual BOOL Unlock() = 0;
  virtual BOOL Unlock(LONG /* lCount */, LPLONG /* lpPrevCount=NULL */)
  { return TRUE; }

  // Implementation
 public:
  virtual ~CSyncObject();
  #ifdef _DEBUG
   CString m_strName;
   virtual void AssertValid() const;
   virtual void Dump(CDumpContext& dc) const;
  #endif
  friend class CSingleLock;
  friend class CMultiLock;
};

  CSyncObject类最主要的两个函数是Lock和Unlock,若我们直接使用CSyncObject类及其派生类,我们需要非常小心地在Lock之后调用Unlock。

  MFC提供的另两个类CSingleLock(等待一个对象)和CMultiLock(等待多个对象)为我们编写应用程序提供了更灵活的机制,下面以实际来阐述CSingleLock的用法:

class CThreadSafeWnd
{
 public:
  CThreadSafeWnd(){}
  ~CThreadSafeWnd(){}
  void SetWindow(CWnd *pwnd)
  {
   m_pCWnd = pwnd;
  }
  void PaintBall(COLORREF color, CRect &rc);
 private:
  CWnd *m_pCWnd;
  CCriticalSection m_CSect;
};

void CThreadSafeWnd::PaintBall(COLORREF color, CRect &rc)
{
 CSingleLock csl(&m_CSect);
 //缺省的Timeout是INFINITE,只有m_Csect被激活,csl.Lock()才能返回
 //true,这里一直等待
 if (csl.Lock())
;
 {
  // not necessary
  //AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  CDC *pdc = m_pCWnd->GetDC();
  CBrush brush(color);
  CBrush *oldbrush = pdc->SelectObject(&brush);
  pdc->Ellipse(rc);
  pdc->SelectObject(oldbrush);
  GdiFlush(); // don't wait to update the display
 }
}

  上述实例讲述了用CSingleLock对Windows GDI相关对象进行保护的方法,下面再给出一个其他方面的例子:

int array1[10], array2[10];
CMutexSection section; //创建一个CMutex类的对象

//赋值线程控制函数
UINT EvaluateThread(LPVOID param)
{
 CSingleLock singlelock;
 singlelock(&section);

 //互斥区域
 singlelock.Lock();
 for (int i = 0; i < 10; i++)
  array1[i] = i;
 singlelock.Unlock();
}
//拷贝线程控制函数
UINT CopyThread(LPVOID param)
{
 CSingleLock singlelock;
 singlelock(&section);

 //互斥区域
 singlelock.Lock();
 for (int i = 0; i < 10; i++)
  array2[i] = array1[i];
 singlelock.Unlock();
}
}

AfxBeginThread(EvaluateThread, NULL); //启动赋值线程
AfxBeginThread(CopyThread, NULL); //启动拷贝线程

  上面的例子中启动了两个线程EvaluateThread和CopyThread,线程EvaluateThread把10个数赋值给数组array1[],线程CopyThread将数组array1[]拷贝给数组array2[]。由于数组的拷贝和赋值都是整体行为,如果不以互斥形式执行代码段:

for (int i = 0; i < 10; i++)
array1[i] = i;

  和

for (int i = 0; i < 10; i++)
array2[i] = array1[i];

  其结果是很难预料的!

  除了可使用CCriticalSection、CEvent、CMutex、CSemaphore作为线程间同步通信的方式以外,我们还可以利用PostThreadMessage函数在线程间发送消息:

BOOL PostThreadMessage(DWORD idThread, // thread identifier
UINT Msg, // message to post
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
进入讨论组讨论。
收藏此文】【 】【打印】【关闭
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
巧巧读书宗旨
相关专题
讨论组问题推荐
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
Photoshop教 程照片处理 照片制作 PS快捷键 抠图
计 算 机 故 障XP系统修复
艺 术 与 设 计设计 流媒体 设计欣赏 边框
计 算 机 安 全ARP
站内频道文章精选
巧巧电脑频道编辑信箱  告诉我们您想看的专题或文章