[消息等待求助]

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
...全文
220 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
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也会出现问题。 或者大家有什么其他可行的方法吗
在老人端,我们通过以下功能来完善系统。 *蓝色欢迎界面 *注册账号(输入两次密码不相同,提示密码输入不一致,手机号只限制输入数字,不允许其他字符输入)注册成功后立即跳转至老人端主界面 *登入账号(需要用户名和密码) *一键求助(只需要事先在个人资料中设置相关信息,然后点击一键求助按钮就能立即发布求助。适合操作能力不强、行动不方便的老人) *定制求助(有操作能力的老人可以根据不同时刻老人的不同需求在特定求助里填写描述具体时间然后传消息给服务器发布求助事件) *当前进度(点击可以查看老人当前求助事件的进度状态,查看后的状态分为三种:求助事件正在等待志愿者应答,志愿者正在帮助中,求助事件已完成请评价。老人评价之后确认可以提交老人的星级评价信息给服务器。) *记录(点击可以查看相关历史记录,历史记录里记录几几年几月几日什么时候,老人发布了一键求助或是特定求助,或是在什么时候老人查看了当前进度为什么状态,记录了一些可以浏览的历史状态和信息) *设置(5个子功能) (1)个人资料(设置头像,选择性别,填写姓名、当前地址,自动获取当前定位,可以选择历史定位点,联系电话、默认支付糖豆数,病史等备注信息) (2)修改密码(输入旧密码,两次输入新密码,进行修改密码) (3)钱包(糖豆转化,糖豆账户余额) (4)跌倒报警(设置紧急联系人电话,短信模板保存后开启跌倒报警功能,获取手机参数在老人可能跌倒时震动并响铃,若一段时间内老人没有按下确认按钮,就会向服务器发送SOS请求帮助,同时向紧急联系人发送短信。) (5)退出登入

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧