[消息等待求助]

wode84320 2014-01-15 09:40:58
我想做一个功能。
1. 通过串口发送数据给下位机,其中下位机接收到数据后需要返回ACK指令,上位机接收到后认为发送成功,否则重新发送上次的数据,最多3次。

实现思路:
1. 一个串口类用来发送接收数据。
2. 串口接收到数据后(在串口的读线程里),发送自定义的消息WM_NEW_DATA_ARRIVED到窗口dlg1。
3. 由于发送数据的时候需要判断是否需要重发数据。采用了while+msgwaitformultiobjects的方法。

最后的出现了一个问题: 开始的时候正常,几次发送后发现程序卡死,界面不响应。

主要代码如下:
1. 发送数据的函数在dlg1中调用
发送前先创建 event
m_hAckEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
在调用发送函数
int SendData(BYTE* pdata, int len)
{
int result=0,nErr=0;
while ( 1 )
{
pSerialCom->WritePort(pdata,len);
bool flags;

flags = WaitMyEvent(m_hAckEvent,40);//等待40ms

if ( flags )
{
ResetEvent(m_hAckEvent);
return TRUE;
}
else
{
nErr++;
if ( nErr >= 3)
{
nErr = 0;
return FALSE;
}
}
}
}

其中WaitMyEvent:
BOOL WaitMyEvent(HANDLE hObject,int timeOut)
{
while (TRUE)
{
MSG msg;

while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// If it's a quit message, we're out of here.
if (msg.message == WM_QUIT)
//return FALSE;
// Otherwise, dispatch the message.
TranslateMessage(&msg);
DispatchMessage(&msg);
} // End of PeekMessage while loop.
// Wait for any message sent or posted to this queue
// or for one of the passed handles be set to signaled.
DWORD result = MsgWaitForMultipleObjects(1, &hObject,
TRUE, timeOut, QS_ALLINPUT);

switch ( result)
{
case WAIT_OBJECT_0:
return TRUE;
break;
case WAIT_OBJECT_0+1:
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
//TranslateMessage(&msg);
DispatchMessage(&msg);
break;
case WAIT_TIMEOUT:
return FALSE;
break;
default:
break;
}
}
}


2. 串口读线程,发送数据接收到 消息到窗口dlg1

ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0);
//如果读取的数据大于0,
if (actualReadLen>0)
{
LeaveCriticalSection(&ceSeries->m_csCommunicationSync);
//触发读取回调函数
::SendMessage(ceSeries->m_pPortOwner,WM_NEW_DATA_ARRIVE,(WPARAM)readBuf,(LPARAM)actualReadLen);
}


3. 在窗口dlg1的消息处理函数中,经过判断后
SetEvent(m_hAckEvent);


今天弄了一下午找不到原因, 猜测是死锁了。 但是不知道怎么分析。
有哪位大神能指点下吗?
先谢谢了!!!!


我的QQ:290953201
...全文
170 点赞 收藏 14
写回复
14 条回复
wode84320 2014年01月16日
WaitMyEvent使用的是 DWORD result = MsgWaitForMultipleObjects(1, &hObject, FALSE, timeOut, QS_ALLINPUT); 貌似处理后不会阻塞主线程的消息。
回复 点赞
孤客天涯 2014年01月16日
界面dlg1里WaitMyEvent,就会阻塞你主线程,另外,SendMessage也是一个阻塞式调用
回复 点赞
wode84320 2014年01月16日
jason_wentzel: 我有一个界面dlg1, 1. dlg1里面调用senddata; 2. senddata里面有一个WaitMyEvent等待事件触发 3. 串口的线程是在界面初始化的时候就打开了的,一直读数据,一有数据就SendMessage到界面dlg1
回复 点赞
孤客天涯 2014年01月16日
SendData在哪里调用,另外不要用SendMessage,改用PostMessage
回复 点赞
wode84320 2014年01月16日
jason_wentzel: 你好,能详细点吗? 我现在 串口接受的已经是独立的线程了。
回复 点赞
孤客天涯 2014年01月16日
采用多线程处理
回复 点赞
wode84320 2014年01月16日
To RobertBaker: 感谢您的回答。 主要是我对这方面不是太懂。 我用的是wince的开发平台。我的过程是每次点击一个按钮,发送消息,然后又会接到下位机的消息,接到后setevent(设置断点发现进入过),然后再WaitMyEvent函数里面设置断点发现 收到了event的激发。 就这样正常几次(有时候十几次)之后,再点击按钮发送就会卡住了,界面也不响应,程序里面设的断点也没进入。 我能否加下你的QQ?
回复 点赞
LiuYinChina 2014年01月16日
程序有调试信息没有? 如果有, 1.可以用 VC Attach 到那个进程, 2.Debug->Break All 3.查看Threads窗口的各线程,根据你的情况应该看看主线程在哪里卡住的,用鼠标双击主线程,看堆栈, 就会发现问题。
回复 点赞
wode84320 2014年01月16日
To schlafenhamster: 你好, 你的意思我还是不太明白。 能麻烦你看看我最开始的问题吗? 好像是阻塞了。不知道怎么解决。我为了保证能 重新 发送上一条指令,用了一个while循环,每次循环都等待ACK信号。 但是我那样做了后就出现了问题,前几次可以正常,后面就卡死了。
回复 点赞
schlafenhamster 2014年01月16日
“如果 100ms 内 接收到数据 (WM_NEW_DATA_ARRIVE) , 关闭 定时器” 就可以发新的了,(还是 打开 定时器, 如 100ms , 如果 100ms 接受 不到 数据 , 再发。。。)
回复 点赞
wode84320 2014年01月16日
或者说, 我想实现的功能就是: 上位机发指令是一问一答的, 没有确认包,则重新发上一条数据。 怎么做呢?
回复 点赞
wode84320 2014年01月16日
To schlafenhamster: 这样有些问题的。 你看我加入要发指令A到下位机,下位机接收到的话返回ACK,我收到ACK继续发下一条指令B。如果没收到ACK或者收到的不是ACK 重新发送指令A。 你用定时器的话,时间是判断了,但是怎么重新发送指令A呢?
回复 点赞
schlafenhamster 2014年01月16日
“上位机接收到后认为发送成功,否则重新发送上次的数据,最多3次” 多长时间 接受 不到 , 就重发 ? 使用 定时器。 第一次发送 打开 定时器, 如 100ms , 如果 100ms 接受 不到 数据 , 再发。 如果 100ms 内 接收到数据 (WM_NEW_DATA_ARRIVE) , 关闭 定时器
回复 点赞
wode84320 2014年01月16日
求助啊!!!!! 找不到原因啊 改用postmessage也会出现问题。 或者大家有什么其他可行的方法吗
回复 点赞
发动态
发帖子
进程/线程/DLL
创建于2007-09-28

6376

社区成员

4.9w+

社区内容

VC/MFC 进程/线程/DLL
社区公告
暂无公告