多个窗口收发WINDOW消息阻塞的一点思考
2013-11-22 00:04
453 查看
在软件项目里有三个模块,分别为
一个应用模块(处理数据)
一个显示模块(屏幕)
一个通信模块(与主机通信)
每个模块都会继承WINDOW收发通信模块基类创建一个属于自己的子窗口,然后在窗口的消息处理函数中对收到的消息进行处理。
在其中一个测试过程中,当通信模块收到主机命令然后向应用模块发送指令,应用模块执行完后,应用模块会向通信模块发送指令执行成功消息。调用
ret = ::SendMessageTimeout(hRecvWnd,// handle to window
WM_COPYDATA,// message type
(WPARAM)hSendWnd,// first message parameter
(LPARAM)&cds,// second message parameter
SMTO_BLOCK,// send options
3000,// time-out duration
&dwResult);// return value for synchronous call
没想到最后执行超时了2次,最后一次才成功。延迟了9秒。
原因是当应用模块发送消息后,基类窗口处理函数调用的接收到的消息处理动作阻塞住了。
解决阻塞有3种方法
1. 把接受到的消息内容,先拷贝起来,然后直接给发送信息的窗口返回消息处理,然后继续对接受到的消息进行处理.
2. 每收到一个消息,创建一个线程,把收到的消息内容存储起来,然后在线程里对接受到的消息进行处理。
3. 把所有接受到的消息内容,拷贝到队列里,然后对队列里的接受到的消息进行处理
最后我选择了用线程,因为这个比较简单,而且线程数量也不多,释放也简单。
原来的窗口消息处理函数为
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COPYDATA:
COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam;
if ((cds!=NULL)&&(m_ipc!=NULL))
{
//m_ipc为CIPC的类对象,
m_ipc->OnReceive(m_csSendWndTile,cds->dwData,cds->lpData,cds->cbData);
}
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
修改后的窗口消息处理函数为:
UINT Thread_Process(LPVOID lpContext)
{
COPYDATASTRUCT* cds = new COPYDATASTRUCT;
memcpy(cds,(COPYDATASTRUCT*)lpContext,sizeof(COPYDATASTRUCT));
if ((cds!=NULL)&&(g_pIPC!=NULL))
{
g_pIPC->OnReceive("",cds->dwData,cds->lpData,cds->cbData);
}
delete []cds;
AfxEndThread(0);
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COPYDATA:
CString appName = AfxGetAppName();
//因为只有应用模块发送消息的时候才会阻塞,而且如果显示模块也用线程的话,那每个线程都带有一个显示屏幕。
//不好处理。通信模块需要自己给自己发送消息,所以如果创建线程的后,就涉及到线程间通信的问题,所以这两个
//模块没有用线程。实际证明也不需要。
if (appName.Compare("通信模块")==0 || appName.Compare("显示模块")==0) //
{
COPYDATASTRUCT *cds = (COPYDATASTRUCT*)lParam;
if ((cds!=NULL)&&(g_pIPC!=NULL))
{
g_pIPC->OnReceive("",cds->dwData,cds->lpData,cds->cbData);
}
}
else
{
AfxBeginThread(Thread_Process,(COPYDATASTRUCT*)lParam);
}
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
一个应用模块(处理数据)
一个显示模块(屏幕)
一个通信模块(与主机通信)
每个模块都会继承WINDOW收发通信模块基类创建一个属于自己的子窗口,然后在窗口的消息处理函数中对收到的消息进行处理。
在其中一个测试过程中,当通信模块收到主机命令然后向应用模块发送指令,应用模块执行完后,应用模块会向通信模块发送指令执行成功消息。调用
ret = ::SendMessageTimeout(hRecvWnd,// handle to window
WM_COPYDATA,// message type
(WPARAM)hSendWnd,// first message parameter
(LPARAM)&cds,// second message parameter
SMTO_BLOCK,// send options
3000,// time-out duration
&dwResult);// return value for synchronous call
没想到最后执行超时了2次,最后一次才成功。延迟了9秒。
原因是当应用模块发送消息后,基类窗口处理函数调用的接收到的消息处理动作阻塞住了。
解决阻塞有3种方法
1. 把接受到的消息内容,先拷贝起来,然后直接给发送信息的窗口返回消息处理,然后继续对接受到的消息进行处理.
2. 每收到一个消息,创建一个线程,把收到的消息内容存储起来,然后在线程里对接受到的消息进行处理。
3. 把所有接受到的消息内容,拷贝到队列里,然后对队列里的接受到的消息进行处理
最后我选择了用线程,因为这个比较简单,而且线程数量也不多,释放也简单。
原来的窗口消息处理函数为
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COPYDATA:
COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam;
if ((cds!=NULL)&&(m_ipc!=NULL))
{
//m_ipc为CIPC的类对象,
m_ipc->OnReceive(m_csSendWndTile,cds->dwData,cds->lpData,cds->cbData);
}
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
修改后的窗口消息处理函数为:
UINT Thread_Process(LPVOID lpContext)
{
COPYDATASTRUCT* cds = new COPYDATASTRUCT;
memcpy(cds,(COPYDATASTRUCT*)lpContext,sizeof(COPYDATASTRUCT));
if ((cds!=NULL)&&(g_pIPC!=NULL))
{
g_pIPC->OnReceive("",cds->dwData,cds->lpData,cds->cbData);
}
delete []cds;
AfxEndThread(0);
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COPYDATA:
CString appName = AfxGetAppName();
//因为只有应用模块发送消息的时候才会阻塞,而且如果显示模块也用线程的话,那每个线程都带有一个显示屏幕。
//不好处理。通信模块需要自己给自己发送消息,所以如果创建线程的后,就涉及到线程间通信的问题,所以这两个
//模块没有用线程。实际证明也不需要。
if (appName.Compare("通信模块")==0 || appName.Compare("显示模块")==0) //
{
COPYDATASTRUCT *cds = (COPYDATASTRUCT*)lParam;
if ((cds!=NULL)&&(g_pIPC!=NULL))
{
g_pIPC->OnReceive("",cds->dwData,cds->lpData,cds->cbData);
}
}
else
{
AfxBeginThread(Thread_Process,(COPYDATASTRUCT*)lParam);
}
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
相关文章推荐
- 多个窗口收发WINDOW消息阻塞的一点思考
- 把消息送到默认窗口函数里,并非一点用都没有,可能会产生新的消息(以WM_WINDOWPOSCHANGED为例)
- 用WindowFromPoint()函数来获得鼠标所在位置的窗口的句柄--发生一个关闭窗口的消息---关闭鼠标所在的窗口
- window窗口消息大全
- 第25周-window程序设计(基础篇)-第3章-窗口消息处理程序WndProc
- window程序设计笔记 第三章 窗口和消息
- 钩子中向窗口发送消息、操作窗口无反应的问题解决方法(Hook dll ShowWindow HWND)
- JS基础第4课:prompt 消息对话框、打开新窗口(window.open
- delphi程序向另一个可执行程序发消息(使用GetForegroundWindow; 找出当前操作系统中活动的第一个窗口)
- window窗口与消息(一)窗口创建
- 判断一个窗口是否被挂起(发WM_NULL消息,或者调用IsHungAppWindow API进行测试)
- window窗口与消息(二)消息循环
- Delphi使用TObject类对象创建接受window消息(使用Classes.AllocateHWnd为对象创建一个尺寸为0的窗口,从而有了Handle)good
- 窗口消息钩子:ShellHook, RegisterShellHookWindow, Hook窗口创建, 闪烁等
- 非主线程创建窗口也能工作正常,只要我们注意一点:消息循环必须要和创建窗口在同一线程!
- 关于SNS消息推送的一点思考
- 【C#】无损转换Image为Icon 【C#】组件发布:MessageTip,轻快型消息提示窗 【C#】给无窗口的进程发送消息 【手记】WebBrowser响应页面中的blank开新窗口及window.close关闭本窗体 【手记】调用Process.EnterDebugMode引发异常:并非所有引用的特权或组都分配给呼叫方 【C#】DataRowState演变备忘
- window消息机制的一点理解
- 第25周-window程序设计(基础篇)-第4章-SYSMETS.C窗口消息处理程序
- 关于设计窗口定时器类的一点思考(2013-03-17)