最近用MFC做一个应用软件,遇到一个问题。运行软件出现一个对话框,对话框中有一个Sensor控件,点击Sensor控件出现一个子对话框,子对话框中是陀螺仪,加速度,光传感器等采集到的数据,数据在一直变化,子对话框最下面有Ok和Cancel按钮,现在的问题是数据更新太慢,而且点击ok或cancel按钮子对话框并不能马上关闭,要等10几秒钟才能关闭,求高手解答????  解答正确马上给分,就剩95分了,全给。急~源代码如下:
#include "stdafx.h"
#include "test.h"
#include "sensor_test.h"
#include "afxdialogex.h"
#include <sensorsapi.h>
#include <sensors.h>
#pragma comment(lib,"setupapi.lib")#define TIME_ID 1#include "senslib.h"
#include <vector>
struct A_SENSOR_DATA
{
PROPERTYKEY key;
PROPVARIANT data;
};struct A_SENSOR
{
ISensor *pISensor_struct;
SENSOR::MySensorEvents se;
std::vector<A_SENSOR_DATA> data;
}*pA_Sensor;
IMPLEMENT_DYNAMIC(sensor_test, CDialogEx) sensor_test::sensor_test(CWnd* pParent /*=NULL*/)
: CDialogEx(sensor_test::IDD, pParent)
{
pA_Sensor = new A_SENSOR;
}sensor_test::~sensor_test()
{
delete pA_Sensor;
}int Stop_Flag = 0;void sensor_test::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(sensor_test, CDialogEx)
ON_WM_TIMER()
ON_BN_CLICKED(IDOK, &sensor_test::OnBnClickedOk)
ON_BN_CLICKED(IDCANCEL, &sensor_test::OnBnClickedCancel)
END_MESSAGE_MAP()const CLSID sens_clsids[] = {
SENSOR_CATEGORY_MOTION         ,
SENSOR_CATEGORY_ORIENTATION    ,
SENSOR_CATEGORY_BIOMETRIC      ,
SENSOR_CATEGORY_LIGHT          
};static void *SensorManager = 0;
ISensorManager *pISensorman = 0;SENSOR::MySensorManagerEvents sme;void sensor_test::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
HRESULT hr  = 0;
LPCTSTR lp1 = L"Accelerometer Sensor(g)";
LPCTSTR lp2 = L"Gyroscope Sensor";
LPCTSTR lp3 = L"Light Sensor(lux)";
LPCTSTR lp4 = L"Magnetic Sensor(uT)";
LPCTSTR lp5 = L"Proximity Sensor(m)"; CDC * pDC=GetDC();
pDC->TextOut( 30 , 50  , lp1 , _tcsclen(lp1));
pDC->TextOut( 30 , 100 , lp2 , _tcsclen(lp2));
pDC->TextOut( 30 , 150 , lp3 , _tcsclen(lp3));
pDC->TextOut( 30 , 200 , lp4 , _tcsclen(lp4));
pDC->TextOut( 30 , 250 , lp5 , _tcsclen(lp5)); CString cs; for(unsigned int i = 0; i < 4; i++)
{
ISensorCollection *ic = 0;
hr = pISensorman->GetSensorsByCategory(sens_clsids[i],&ic);
if(!ic)
continue;
ULONG pC = 0;
hr = ic->GetCount(&pC);
if(!pC)
{
ic->Release();
continue;
}
//#if 0
for(unsigned int y = 0; y < pC; y ++)
{
// if(Stop_Flag)
// {
// KillTimer(TIME_ID);
// CDialogEx::OnCancel();
// } ISensor *pISensor;
hr = ic->GetAt(y,&pISensor);    //GetAt方法检索指向ISensor的指针
if(!pISensor)
continue;
//#if 0
pA_Sensor->pISensor_struct = pISensor;
hr = pISensor->SetEventSink(&pA_Sensor->se);   //通过调用SetEventSink方法设置通过其接收传感器事件通知的接口
ISensorDataReport *pISensordatareport;
pISensor->GetData(&pISensordatareport);   //调用GetData方法检索最近的传感器数据报告
if(!pISensordatareport)
continue;
IPortableDeviceKeyCollection* ck;
hr = pISensor->GetSupportedDataFields(&ck);  //调用GetSupportedDataFields检索一组传感器提供的数据字段的PROPERTYKEY
if (SUCCEEDED(hr))
{
ULONG C = 0;
hr = ck->GetCount(&C);     //调用GetCount方法得到IPortableDeviceKeyCollection集合中key的数目
pA_Sensor->data.clear();
for(unsigned int y = 0 ; y < C ; y++)
{
PROPERTYKEY pk;
hr = ck->GetAt(y,&pk);  //调用GetAt方法通过index从IPortableDeviceKeyCollection集合中得到PROPERTYKEY
if (SUCCEEDED(hr))
{
PROPVARIANT pv;
hr = pISensordatareport->GetSensorValue(pk,&pv);   //通过GetSensorValue方法从数据报告中检索单个数据字段值
if(SUCCEEDED(hr))
{
if(pk.fmtid == SENSOR_DATA_TYPE_ORIENTATION_GUID)     //Compass
{
if(pk.pid == 19)
{
float ORIENTATION_X = pv.date;
cs.Format(_T( "X : %2.3f "),ORIENTATION_X); 
pDC->TextOut( 30 , 225 , cs , _tcsclen(cs));
}
else if(pk.pid == 20)
{
float ORIENTATION_Y = pv.date;
cs.Format(_T( "Y : %2.3f "),ORIENTATION_Y); 
pDC->TextOut( 130 , 225 , cs , _tcsclen(cs));
}
else if(pk.pid == 21)
{
float ORIENTATION_Z = pv.date;
cs.Format(_T( "Z : %2.3f "),ORIENTATION_Z); 
pDC->TextOut( 230 , 225 , cs , _tcsclen(cs));
}
else
{
;
}

else if(pk.fmtid == SENSOR_DATA_TYPE_MOTION_GUID)   
{                                                //Gyroscope
if(pk.pid == 10)
{
float GYROSCOPE_X = pv.date;
cs.Format(_T( "X : %5f "),GYROSCOPE_X); 
pDC->TextOut( 30 , 125 , cs , 10);
}
else if(pk.pid == 11)
{
float GYROSCOPE_Y = pv.date;
cs.Format(_T( "Y : %5f "),GYROSCOPE_Y); 
pDC->TextOut( 130 , 125 , cs , 10);
}
else if(pk.pid == 12)
{
float GYROSCOPE_Z = pv.date;
cs.Format(_T( "Z : %5f "),GYROSCOPE_Z); 
pDC->TextOut( 230 , 125 , cs , 10);
}
else if(pk.pid == 2)                           //Acclerometer

float ACCLEROMETER_X = pv.date; 
cs.Format(_T( "X : %5f "),ACCLEROMETER_X); 
pDC->TextOut( 30 , 75 , cs , 10);
}
else if(pk.pid == 3)
{
float ACCLEROMETER_Y = pv.date;
cs.Format(_T( "Y : %5f "),ACCLEROMETER_Y); 
pDC->TextOut( 130 , 75 , cs , 10);
}
else if(pk.pid == 4)
{
float ACCLEROMETER_Z = pv.date;
cs.Format(_T( "Z : %5f "),ACCLEROMETER_Z); 
pDC->TextOut( 230 , 75 , cs , 10);
}
else
{
;
}
}
else if(pk.fmtid == SENSOR_DATA_TYPE_BIOMETRIC_GUID)     //Proximity
{
if(pk.pid == 3)
{
float PROXIMITY = pv.date;
cs.Format(_T( "%3f "),PROXIMITY); 
pDC->TextOut( 30 , 275 , cs , _tcsclen(cs));
}
else
{
;
}
}
else if(pk.fmtid == SENSOR_DATA_TYPE_LIGHT_GUID)     //Light
{
if(pk.pid == 2)
{
float LIGHT = pv.fltVal;
cs.Format(_T( "%3.2f "),LIGHT); 
pDC->TextOut( 30 , 175 , cs , _tcsclen(cs));
}
else
{
;
}
}
else
{
;
}
}
} }
ck->Release();
}
//#endif
pISensordatareport->Release();
pISensor->Release();
}
//#endif
ic->Release();
}
CDialogEx::OnTimer(nIDEvent);
}
BOOL sensor_test::OnInitDialog()
{
CDialogEx::OnInitDialog(); CoCreateInstance(CLSID_SensorManager,
0,
CLSCTX_ALL,
__uuidof(ISensorManager),
(void**)&SensorManager
);
pISensorman = (ISensorManager*)SensorManager;
pISensorman->SetEventSink(&sme);
this->SetTimer(TIME_ID,400,NULL);
return TRUE;  
}void sensor_test::OnBnClickedOk()
{ ::WritePrivateProfileStringA(
"Sensor_Test",
"Result ",
" Pass",
"..\\v98_function_test.ini"
);
Sensor_flag = 1;
Stop_Flag = 1;
CDialogEx::OnOK();
Stop_Flag = 0;
}void sensor_test::OnBnClickedCancel()
{ ::WritePrivateProfileStringA(
"Sensor_Test",
"Result ",
" Fail",
"..\\v98_function_test.ini"
);
Sensor_flag = 2;
Stop_Flag = 1;
CDialogEx::OnCancel();
Stop_Flag = 0;
}

解决方案 »

  1.   

    代码没有格式,没法看...大致看了看,timer里确实做的东西太多了。无法及时更新可能就是线程队列中消息太多,无法及时处理。最后ok或cancel的时候,等到队列消息处理完毕后才会处理按键响应,所以会有延迟最好用多线程吧
      

  2.   

    楼主的状况就是界面线程卡死了嘛。
    老问题了。1.自己建立一个专门的线程来接收传感器数据(最好去参考一些串口编程代码),将数据处理和界面显示分离
    2.接收线程已SendMessage的方式通知界面线程刷新。
    3.我曾经做过加速度传感器的模拟曲线,记得用环形缓冲区(毕竟你能显示的曲线就那一部分)
    这个大大的可以增加效率。
      

  3.   

    涉及大量数据处理的操作就放到一个线程中去处理吧,你的OnTimer处理绘图本来就够卡了
      

  4.   

    感谢各位热心回答。tiger9991 , 在尝试你说的,单独开了一个接受数据的线程。
    2.接收线程已SendMessage的方式通知界面线程刷新。
    能具体讲讲这一步要怎么具体实现吗? SendMessage发送设呢消息? 界面线程怎么判断数据有变化而刷新呢?
    水平较次,请直接具体指教。
      

  5.   

    感谢各位热心回答。tiger9991 , 在研究你说的,去掉了定时器更新,单独开了一个接收数据的线程。
    2.接收线程已SendMessage的方式通知界面线程刷新。
    这一步具体该怎么实现呢? SendMessage应该发送什么消息呢? 界面线程怎么判断数据变化来刷新屏幕上数据呢? 最好有个具体的例子code, 水平较次,请具体直接指教!谢谢了。
      

  6.   

    感谢各位热心回答。tiger9991 , 在研究你说的,去掉了定时器更新,单独开了一个接收数据的线程。
    2.接收线程已SendMessage的方式通知界面线程刷新。
    这一步具体该怎么实现呢? SendMessage应该发送什么消息呢? 界面线程怎么判断数据变化来刷新屏幕上数据呢? 最好有个具体的例子code, 水平较次,请具体直接指教!谢谢了。
      

  7.   

    不要界面线程里搞recv传感器的数据. 开个work_thread 吧. 整完了再post数据给ui如何. 
      

  8.   

    SendMessage发送给主界面。
    消息可以自定义,句柄的话把参数传进来可以强转GetSafeHwnd(),后面两个参数自定义或者NULL都可以
    主要是启动一个通知作用主界面画图就可以了
      

  9.   

    能具体讲讲这一步要怎么具体实现吗? SendMessage发送设呢消息? SendMessage(句柄,自定义消息编号,参数1,参数2)
    上面说了界面线程怎么判断数据有变化而刷新呢?
    数据接收到一定程度,你觉得OK了,就SendMessage(句柄,自定义消息编号,参数1,参数2)
    触发主界面画图
      

  10.   


    你好,请问可以联系一下你么,关于你上传的Win8 camera应用,很急