技术开发 频道

VC中利用多线程实现线程之间的通信

    3、线程之间的通信

   
通常情况下,一个次级线程要为主线程完成某种特定类型的任务,这就隐含着表示在主线程和次级线程之间需要建立一个通信的通道。一般情况下,有下面的几种方法实现这种通信任务:使用全局变量(上一节的例子其实使用的就是这种方法)、使用事件对象、使用消息。这里我们主要介绍后两种方法。

    (一) 利用用户定义的消息通信

    在Windows程序设计中,应用程序的每一个线程都拥有自己的消息队列,甚至工作线程也不例外,这样一来,就使得线程之间利用消息来传递信息就变的非常简单。首先用户要定义一个用户消息,如下所示:#define WM_USERMSG WMUSER+100;在需要的时候,在一个线程中调用::PostMessage((HWND)param,WM_USERMSG,0,0)或CwinThread::PostThradMessage()来向另外一个线程发送这个消息,上述函数的四个参数分别是消息将要发送到的目的窗口的句柄、要发送的消息标志符、消息的参数WPARAM和LPARAM。下面的代码是对上节代码的修改,修改后的结果是在线程结束时显示一个对话框,提示线程结束:
UINT ThreadFunction(LPVOID pParam) {  while(!bend)  {   Beep(100,100);   Sleep(1000);  }  ::PostMessage(hWnd,WM_USERMSG,0,0);  return 0; } ////////WM_USERMSG消息的响应函数为OnThreadended(WPARAM wParam, LPARAM lParam) LONG CTestView::OnThreadended(WPARAM wParam,LPARAM lParam) {  AfxMessageBox("Thread ended.");  Retrun 0; }



    上面的例子是工作者线程向用户界面线程发送消息,对于工作者线程,如果它的设计模式也是消息驱动的,那么调用者可以向它发送初始化、退出、执行某种特定的处理等消息,让它在后台完成。在控制函数中可以直接使用::GetMessage()这个SDK函数进行消息分检和处理,自己实现一个消息循环。GetMessage()函数在判断该线程的消息队列为空时,线程将系统分配给它的时间片让给其它线程,不无效的占用CPU的时间,如果消息队列不为空,就获取这个消息,判断这个消息的内容并进行相应的处理。

    (二)用事件对象实现通信

    在线程之间传递信号进行通信比较复杂的方法是使用事件对象,用MFC的Cevent类的对象来表示。事件对象处于两种状态之一:有信号和无信号,线程可以监视处于有信号状态的事件,以便在适当的时候执行对事件的操作。上述例子代码修改如下:

//////////////////////////////////////////////////////////////////// Cevent threadStart ,threadEnd; UINT ThreadFunction(LPVOID pParam) {  ::WaitForSingleObject(threadStart.m_hObject,INFINITE);  AfxMessageBox("Thread start.");  while(!bend)  {   Beep(100,100);   Sleep(1000);   Int result=::WaitforSingleObject(threadEnd.m_hObject,0);   //等待threadEnd事件有信号,无信号时线程在这里悬停   If(result==Wait_OBJECT_0)    Bend=TRUE;  }  ::PostMessage(hWnd,WM_USERMSG,0,0);  return 0; } ///////////////////////////////////////////////////////////// Void CtestView::OninitialUpdate() {  hWnd=GetSafeHwnd();  threadStart.SetEvent();//threadStart事件有信号  pThread=AfxBeginThread(ThreadFunction,hWnd);//启动线程  pThread->m_bAutoDelete=FALSE;  Cview::OnInitialUpdate(); } //////////////////////////////////////////////////////////////// Void CtestView::OnDestroy() {  threadEnd.SetEvent();  WaitForSingleObject(pThread->m_hThread,INFINITE);  delete pThread;  Cview::OnDestroy(); }

    运行这个程序,当关闭程序时,才显示提示框,显示"Thread ended"。

0
相关文章