WINCE下进程间通信(二)

     接着前面的文章《WINCE下进程间通信(一)》,现在介绍进程间通信的另一种方法。

 三、管道(消息队列)

       WINCE并不支持类似于PC机上匿名管道、命名管道的通信方式,但CE下提供了一种点对点消息队列的方法,其工作原理与管道非常类似:在通信的两端分别建立一个读队列和写队列,写进程往消息队列一端写入数据,读进程从消息队列另一端读取数据。

       消息队列相关的系统API主要有:CreateMsgQueue()、ReadMsgQueue()、WriteMsgQuue()和CloseMsgQueue()。为了方便消息队列的操作,封装了一个消息队列操作类,参考代码如下:

       头文件(CMsgQueue.h)/******************************************************************* filename: CMsgQueue.h purpose: 封装了WINCE下消息队列操作类 author: firehood created: 2011.03.23 ********************************************************************/ #ifndef _MSG_QUEUE_H #define _MSG_QUEUE_H // 消息队列访问模式 enum ACCESSMODE { ReadMode = 0, WriteMode }; // 定义消息回调函数 typedef BOOL (CALLBACK *MsgQueueCallBack)(PVOID pData, DWORD dwSize); class CMsgQueue { public: CMsgQueue(); CMsgQueue(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode); ~CMsgQueue(); public: /********************************************************************** 函数名:Create 功能: 创建或打开消息队列 参数: [in]lpQueueName: 消息队列名称 [in]dwSize: 每条消息的最大长度 [in]accessMode 消息队列访问模式 ReadMode:只读 WriteMode:只写 返回值: 成功:TRUE 失败:FALSE **********************************************************************/ BOOL Create(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode); /********************************************************************** 函数名:Read 功能: 从消息队列中读取一条消息 参数: [out]lpBuffer: 存放读取的数据 [in] dwSize: 读取数据的大小 [out]lpNumberOfBytesRead 实际读取数据的大小 [in] dwTimeout 读取超时时间(ms) 0 立即返回 INFINITE 永远等待直至消息队列中有数据 返回值: 成功:TRUE 失败:FALSE ***********************************************************************/ BOOL Read(LPVOID lpBuffer,DWORD dwSize,LPDWORD lpNumberOfBytesRead,DWORD dwTimeout = 0); /********************************************************************** 函数名:Write 功能: 向消息队列中写入一条消息 参数: [in]lpBuffer: 待写入的数据 [in]dwSize: 写入数据的大小 返回值: 成功:TRUE 失败:FALSE **********************************************************************/ BOOL Write(LPVOID lpBuffer,DWORD dwSize); // 设置消息回调函数 BOOL SetMsgCallBack(MsgQueueCallBack pCallBackFun, PVOID pParam); // 关闭消息队列 void Close(void); private: // 开启读取消息线程 BOOL StartRevMsgThread(void); // 停止读取消息线程 BOOL StopRevMsgThread(void); // 读取消息线程 static void WINAPI RevMsgThread(LPVOID pParam); private: HANDLE m_hMsgQueue; DWORD m_dwQueueSize; MsgQueueCallBack m_MsgCallBack; HANDLE m_hRevMsgThread; BOOL m_bThreadExit; }; #endif

 源文件(CMsgQueue.cpp)

#include "stdafx.h" #include "CMsgQueue.h" CMsgQueue::CMsgQueue() { m_hMsgQueue = NULL; m_dwQueueSize = 0; m_hRevMsgThread = NULL; m_bThreadExit = FALSE; m_MsgCallBack = NULL; } CMsgQueue::CMsgQueue(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode) { Create(lpQueueName,dwSize,accessMode); } CMsgQueue::~CMsgQueue() { Close(); } BOOL CMsgQueue::Create(LPCWSTR lpQueueName,DWORD dwSize,ACCESSMODE accessMode) { if(!m_hMsgQueue) { m_hRevMsgThread = NULL; m_bThreadExit = FALSE; m_MsgCallBack = NULL; m_dwQueueSize = dwSize; // 创建消息队列 MSGQUEUEOPTIONS options; options.dwSize = sizeof(options); options.dwFlags = MSGQUEUE_NOPRECOMMIT|MSGQUEUE_ALLOW_BROKEN; options.dwMaxMessages = 0; options.cbMaxMessage = dwSize; options.bReadAccess = (accessMode==ReadMode) ? TRUE : FALSE; m_hMsgQueue =::CreateMsgQueue(lpQueueName,&options); } return TRUE; } void CMsgQueue::Close(void) { if(m_hMsgQueue) { ::CloseMsgQueue(m_hMsgQueue); m_hMsgQueue = NULL; } // 注销回调函数 SetMsgCallBack(NULL,NULL); } BOOL CMsgQueue::Read(LPVOID lpBuffer,DWORD dwSize,LPDWORD lpNumberOfBytesRead,DWORD dwTimeout) { if(m_hMsgQueue == NULL || lpBuffer == NULL) { return FALSE; } DWORD dwFlag = 0; // 从消息队列头部读出数据 if(!::ReadMsgQueue(m_hMsgQueue,lpBuffer,dwSize,lpNumberOfBytesRead,dwTimeout,&dwFlag)) { return FALSE; } return TRUE; } BOOL CMsgQueue::Write(LPVOID lpBuffer,DWORD dwSize) { if(m_hMsgQueue == NULL || lpBuffer == NULL) { return FALSE; } // 向消息队列尾部写入数据 if(!::WriteMsgQueue(m_hMsgQueue,lpBuffer,dwSize,0,0)) { return FALSE; } return TRUE; } BOOL CMsgQueue::SetMsgCallBack(MsgQueueCallBack pCallBackFun, PVOID pParam) { m_MsgCallBack = pCallBackFun; if (m_MsgCallBack) { if (m_hRevMsgThread == NULL) { // 开启读取线程 return StartRevMsgThread(); } } else { if (m_hRevMsgThread) { // 关闭读取线程 return StopRevMsgThread(); } } return TRUE; } BOOL CMsgQueue::StartRevMsgThread(void) { if(m_hRevMsgThread == NULL) { // 创建读取消息线程 m_hRevMsgThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CMsgQueue::RevMsgThread, this, 0, NULL); } return (m_hRevMsgThread ? TRUE : FALSE); } BOOL CMsgQueue::StopRevMsgThread(void) { if(m_hRevMsgThread) { m_bThreadExit = TRUE; // 等待线程成功退出 WaitForSingleObject(m_hRevMsgThread,INFINITE); CloseHandle(m_hRevMsgThread); m_hRevMsgThread = NULL; m_hRevMsgThread = FALSE; } return ((m_hRevMsgThread==NULL) ? TRUE : FALSE); } void WINAPI CMsgQueue::RevMsgThread(LPVOID pParam) { CMsgQueue *pMsgQueue=(CMsgQueue*)pParam; LPVOID lpBuffer; DWORD dwReadNums=0; lpBuffer=(LPVOID)malloc(pMsgQueue->m_dwQueueSize); while(!pMsgQueue->m_bThreadExit) { if(!pMsgQueue->m_hMsgQueue ) break; // 从消息队列中读取一条消息(阻塞模式) BOOL ret=pMsgQueue->Read(lpBuffer,pMsgQueue->m_dwQueueSize,&dwReadNums,INFINITE); printf("Read ret=%d,dwReadNums=%d/n",ret,dwReadNums); if(dwReadNums>0) { // 调用回调函数 if(pMsgQueue->m_MsgCallBack) pMsgQueue->m_MsgCallBack(lpBuffer,dwReadNums); } } printf("RevMsgThread exit.../n"); free(lpBuffer); }

 使用CMsgQueue类实现进程间通信:

// 发送进程 ////////////////////////////////////////////////////////////////////////////////// // 创建只写消息队列 CMsgQueue cMsgQueue(L"MsgQueueTest",1024,WriteMode); // 往消息队列写数据 cMsgQueue.Write(L"Hello Word!",22); cMsgQueue.Close(); ////////////////////////////////////////////////////////////////////////////////// // 接收进程 ////////////////////////////////////////////////////////////////////////////////// // 声明消息回调函数 BOOL CALLBACK RecvMsgProc(PVOID pData, DWORD dwSize); // 创建只读消息队列 CMsgQueue cMsgQueue(L"MsgQueueTest",1024,ReadMode); // 设置消息回调函数 cMsgQueue.SetMsgCallBack(RecvMsgProc,NULL); // 处理消息 BOOL CALLBACK RecvMsgProc(PVOID pData, DWORD dwSize) { printf("RecvMsgProc:Rev data Size=%d/n",dwSize); wchar_t data[256]; memcpy(data, pData,dwSize); return TRUE; } //////////////////////////////////////////////////////////////////////////////////

你可能感兴趣的:(api,null,Class,callback,WinCE,winapi)