消息响应响应函数的while循环的成员变量值不会变化

asdjy123 2013-09-23 10:44:24
关键就是程序中的CopyMemory(&IEDValue,&recvData,sizeof(CRealValue));//
IedNum = IEDValue.IedNum;///
这两句,问题出现在:到第二循环时,不会执行第一个循环,使第二个的循环中的变量变化从而跳出第二个循环。

注:我分别用实际装置和用串口精灵模拟装置进行测试过,前者不可以而后者可以,两者的区别只是发报文的频率不同。



CMainFrame成员变量CRealValue IEDValue;//实时的遥测或遥信值

//从共享内存中得到遥测遥信数据
bool CMainFrame::DealComData()
{
CRealValue recvData;
////////第一个循环///
while(m_bThread_RecvData)//从别的地方得到类对象IEDValue值变化的循环
{
ShareMemComCli.GetMemData(&recvData);/
CopyMemory(&IEDValue,&recvData,sizeof(CRealValue));//把得到的实时新数据给对象IEDValue,会使其值不断变化 这里就是数据的变化来源
IedId=IEDValue.IedNum;
//有遥测数据
if((IedId>0) && (IEDValue.type == YC_TYPE))
{
storeCurveData();//保存数据到数据库中
}
}

return true;
}

// 保存曲线数据
BOOL CMainFrame::storeCurveData()
{
....
static int Minute = 0;
int timeM;
timeM = GetTimeValue(Minute,TRUE);
if(timeM >5)//自定义时间定时,5分钟一次
{
PostMessage(WM_YC_DATA,0,0);
}
return true;
}

//提取保存5分钟遥测数据到数据库中
LESULT CMainFrame::storeYcData(WPARAM wParam,LPARAM lParam)
{
.....
///第二个循环/////
while(count)
{
CString strYc =pApp->YcConfigeIed.GetAt(i);
int YcNum =GetNumFromStr(strYc,0,_T(":"));
IedNum = IEDValue.IedNum;///问题就出现在这里,IEDValue里面的值一直都没变,使得这个循环变成死循环了,使得除了这个循环外其他的程序都不执行了
if(YcNum == IedNum)//当装置号相同
{
.......
}

}
catch(_com_error &e)
{
AfxMessageBox(e.Description());
return FALSE;
}
return TRUE;
}
...全文
409 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2013-09-27
  • 打赏
  • 举报
回复
Well Done !
asdjy123 2013-09-27
  • 打赏
  • 举报
回复
总结:1、出现这种错误的原因:经过PostMessage发送消息的响应函数与执行PostMessage的函数是在同一线程中。2、要想第一个While()循环的代码也执行要在 第二个while(1)里交出控制权:GetMessage((&msg, NULL, 0, 0)、TranslateMessage(&msg)和DispatchMessage(&msg);能实现交出控制权语句。 错误之处请指教。
schlafenhamster 2013-09-25
  • 打赏
  • 举报
回复
是的 如果 第二个while(1){} 是空的 话 肯定死了, 第二个while(1)里 必须要有 ,交出控制权的 语句。
asdjy123 2013-09-25
  • 打赏
  • 举报
回复
引用 26 楼 schlafenhamster 的回复:
第一个 PostMessage(WM_YC_DATA,0,0); 如果 成功,进入: while(1){ } ;// 一到这里 ,第一个循环 就执行不到了。// 看 循环里 有没有 把 控制权 给 系统 的 调用, 好让系统 调度 第一个循环。但: 即使第一个循环能执行 PostMessage(WM_YC_DATA,0,0); 这个消息也可能 会 丢失
“一到这里 ,第一个循环 就执行不到了。// 看 循环里 有没有 把 控制权 给 系统 的 调用,” 您的意思是在成功进入第二个while(1)循环之后,如果第二个循环是个死循环,就不会把控制权给系统的调用了?那么在执行第二个while(1)死循环的条件下整个程序也就不会有机会执行第一个while(1)循环了??
路人乙2019 2013-09-24
  • 打赏
  • 举报
回复
引用 19 楼 asdjy123 的回复:
[quote=引用 17 楼 Saleayas 的回复:] 把 IedId 设置为 volatile 监视变量 ,在 IedId =IEDValue.IedNum 设置,在另外线程中之间检测这个 v 变量 。 不是直接把 IEDValue 设置为 v 变量, v 变量不能乱用,会降低性能的。 // Keyword volatile is used as a hint to the compiler that this data // member is accessed by multiple threads.
使用过了,不是volatile的问题,而是循环1的程序根本没执行
引用 18 楼 zzdmfk 的回复:
[quote=引用 16 楼 asdjy123 的回复:] [quote=引用 13 楼 zzdmfk 的回复:] 1.对成员变量操作未同步//事件,关键代码段,sendmessage 2.copymemory前最好清零内存 zeromemory(&recvData); zeromemory(&IEDValue);         ShareMemComCli.GetMemData(&recvData);/         CopyMemory(&IEDValue,&recvData,sizeof(CRealValue));//把得到的实时新数据给对象IEDValue,会使其值不断变化   这里就是数据的变化来源 3.最好不要在工作线程中调用ui类成员函数,而是发送消息。
你的意思是否是再创建一个线程进行处理??[/quote] 没必要,放 ComThreadFun 里面。[/quote] 程序要频繁调用(大约300ms一次,长时间的)这样进行zeromemory(&IEDValue)会有影响吗? [/quote]怕有影响的话,你每次都动态分配idevalue,再通过postmessage的参数把指针发过去。或者放入链表或队列里面,只要注意访问链表时同步就行了
2029952291 2013-09-24
  • 打赏
  • 举报
回复
这两句,问题出现在:到第二循环时,不会执行第一个循环,使第二个的循环中的变量变化从而跳出第二个循环。 大主宰 kenan8.com/b/dazhuzai 注:我分别用实际装置和用串口精灵模拟装置进行测试过,前者不可以而后者可以,两者的区别只是发报文的频率不同。
schlafenhamster 2013-09-24
  • 打赏
  • 举报
回复
是“while(count)”count 不变 ?
schlafenhamster 2013-09-24
  • 打赏
  • 举报
回复
第一个 PostMessage(WM_YC_DATA,0,0); 如果 成功,进入: while(1){ } ;// 一到这里 ,第一个循环 就执行不到了。// 看 循环里 有没有 把 控制权 给 系统 的 调用, 好让系统 调度 第一个循环。但: 即使第一个循环能执行 PostMessage(WM_YC_DATA,0,0); 这个消息也可能 会 丢失
asdjy123 2013-09-24
  • 打赏
  • 举报
回复
引用 24 楼 schlafenhamster 的回复:
是这样的吧? int a() { //第一个循环 while(1) { PostMessage(WM_YC_DATA,0,0); while(1){ } ;// 一到这里 ,第一个循环 就执行不到了。 } }
不是的,第二个while(1){}的在WM_YC_DATA的响应函数里c()(注:与a()应该是同一级别的函数)。
schlafenhamster 2013-09-24
  • 打赏
  • 举报
回复
是这样的吧? int a() { //第一个循环 while(1) { PostMessage(WM_YC_DATA,0,0); while(1){ } ;// 一到这里 ,第一个循环 就执行不到了。 } }
asdjy123 2013-09-24
  • 打赏
  • 举报
回复
[quote=引用 20 楼 schlafenhamster 的回复:] 是quote] 不是“while(count)”count“ 不变 ,是“IedNum = IEDValue.IedNum”值不变,而这个值的变化是在执行第一个while循环才会变的 到现在虽说我用别的方法处理了我的问题,但还是有一点现在还有一点疑问,如:

int a()
{
   //第一个循环
      while(1)
      {
        b();  
      }
} 
int b()
{
    PostMessage(WM_YC_DATA,0,0);
}  
   //WM_YC_DATA的自定义消息响应函数
 int c()
{
      
//第二个循环
       while(1)
      {

       }
} 
是不是程序在 c()中第二个死循环运行中,第一个a()中的程序就不会运行了,PostMessage不是发送之后继续运行原来的程序(即继续运行a()的程序)的吗? 给位大神指教
schlafenhamster 2013-09-23
  • 打赏
  • 举报
回复
“while(m_bThread_RecvData)//从别的地方得到类对象IEDValue值变化的循环” 频率不也一样时,这个值变掉了。
xiaohuh421 2013-09-23
  • 打赏
  • 举报
回复
你第一个循环都没有跳出来, 那就是你的程序逻辑设计有问题了撒. 贴出你的线程函数的写源码吧. 估计是你调用顺序错了, 可能你代码里虽然是先写的循环1,再循环2, 但是执行的时候,循环1被跳过了, 直接到了循环2. 下断点调试吧, 这样的原因很容易找的.
asdjy123 2013-09-23
  • 打赏
  • 举报
回复
引用 3 楼 Saleayas 的回复:
当循环优化时,这个变量就在寄存器内了。 如果是多线程同时处理这个变量,至少需要使用 volatile 。
不是volatile的原因,我重新定义一个volatile int IdNum;发现还是没有变化,关键还是在于循环2根本没跳出来,一直执行。循环根本就在没执行过。 难道是循环1和循环2在同一个线程的原因,我还有再创建一个工作线程进行处理循环2??????? 各位大神有什么好建议
asdjy123 2013-09-23
  • 打赏
  • 举报
回复
引用 3 楼 Saleayas 的回复:
当循环优化时,这个变量就在寄存器内了。 如果是多线程同时处理这个变量,至少需要使用 volatile 。
出现 1>e:\hgdrawyun\drawyun\mainfrm.cpp(372): error C2664: 'memcpy' : cannot convert parameter 1 from 'volatile CRealValue *' to 'void *' 1> Conversion loses qualifiers, 居然不能用CopyMemory()了
Saleayas 2013-09-23
  • 打赏
  • 举报
回复
当循环优化时,这个变量就在寄存器内了。 如果是多线程同时处理这个变量,至少需要使用 volatile 。
asdjy123 2013-09-23
  • 打赏
  • 举报
回复
引用 1 楼 oyljerry 的回复:
是不是数据频率导致CopyMemory函数出问题了
这个不会,原先没加 storeCurveData()在高频率也没出问题(因代码多,所以显示的只是部分代码), 还有CMainFrame::DealComData() 是我开的工作线程,专门处理接收数据、通过消息发给需要的部分
static UINT ComThreadFun (LPVOID pParam)
{  
	CMainFrame *pFrame=(CMainFrame *) pParam;
	pFrame->DealComData();
	return 0;
}
oyljerry 2013-09-23
  • 打赏
  • 举报
回复
是不是数据频率导致CopyMemory函数出问题了
asdjy123 2013-09-23
  • 打赏
  • 举报
回复
引用 17 楼 Saleayas 的回复:
把 IedId 设置为 volatile 监视变量 ,在 IedId =IEDValue.IedNum 设置,在另外线程中之间检测这个 v 变量 。 不是直接把 IEDValue 设置为 v 变量, v 变量不能乱用,会降低性能的。 // Keyword volatile is used as a hint to the compiler that this data // member is accessed by multiple threads.
使用过了,不是volatile的问题,而是循环1的程序根本没执行
引用 18 楼 zzdmfk 的回复:
[quote=引用 16 楼 asdjy123 的回复:] [quote=引用 13 楼 zzdmfk 的回复:] 1.对成员变量操作未同步//事件,关键代码段,sendmessage 2.copymemory前最好清零内存 zeromemory(&recvData); zeromemory(&IEDValue);         ShareMemComCli.GetMemData(&recvData);/         CopyMemory(&IEDValue,&recvData,sizeof(CRealValue));//把得到的实时新数据给对象IEDValue,会使其值不断变化   这里就是数据的变化来源 3.最好不要在工作线程中调用ui类成员函数,而是发送消息。
你的意思是否是再创建一个线程进行处理??[/quote] 没必要,放 ComThreadFun 里面。[/quote] 程序要频繁调用(大约300ms一次,长时间的)这样进行zeromemory(&IEDValue)会有影响吗?
路人乙2019 2013-09-23
  • 打赏
  • 举报
回复
引用 16 楼 asdjy123 的回复:
[quote=引用 13 楼 zzdmfk 的回复:] 1.对成员变量操作未同步//事件,关键代码段,sendmessage 2.copymemory前最好清零内存 zeromemory(&recvData); zeromemory(&IEDValue);         ShareMemComCli.GetMemData(&recvData);/         CopyMemory(&IEDValue,&recvData,sizeof(CRealValue));//把得到的实时新数据给对象IEDValue,会使其值不断变化   这里就是数据的变化来源 3.最好不要在工作线程中调用ui类成员函数,而是发送消息。
你的意思是否是再创建一个线程进行处理??[/quote] 没必要,放 ComThreadFun 里面。
加载更多回复(10)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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