void CVEPView::SampleSetup()
{
do{
       FlashCount++;   //启动画黑白棋盘格图
  drawpad.ShowWindow(TRUE);
  drawpad.RunDraw();
   //调用从A/D读取数据的线程
   gm_pThread = AfxBeginThread(&Thread_IO_InData,NULL);
    }while(FlashCount<FlashTotalCount);

//关闭闪烁棋盘格以及清零闪烁次数
drawpad.ShowWindow(FALSE);
FlashCount=0; 
//数据保存,并把采样到的数据保存到txt文本文件中
CFile file("tempData.txt",CFile::modeCreate | CFile::modeWrite);
CString str="";
for(int i=0;i<CountReadData;i++)
{
str.Format("%f",firstdata[i]);
if(((i+1)!=0)&&((i+1)%10==0))
str=str+"\r\n";
else
str=str+',';
file.Write(str,str.GetLength());
}
file.Close();

AfxMessageBox("数据采样完成!");
//采样数据计数器清零
CountReadData=0;
}
UINT Thread_IO_InData(LPVOID pParam)//从A/D板读取数据的线程

CVEPView  *pView = NULL;
CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;
pView = (CVEPView*) pFrame->GetActiveView(); 
     //采样数据,采样的总时间长度等于闪烁的总次数乘以棋盘格时间频率的倒数;棋盘格时间频率的倒数等于0.5毫秒(采样率为2000次/秒)乘以PerSampleTotalCount
for(pView->PerSampleCount = 0; pView->PerSampleCount < pView->PerSampleTotalCount; pView->PerSampleCount++)
{
pView->SampleData();
pView->DelayTime(470);//进行延时,使读取每个数据的时间接近500毫秒(采样率2000次/秒)
     }  AfxEndThread(0);
return 0;
}
上面的CVEPView::SampleSetup()是我按下界面上一个按钮触发的函数,Thread_IO_InData(LPVOID pParam)是gm_pThread = AfxBeginThread(&Thread_IO_InData,NULL);这条语句所调用的线程,此线程完成工作为从A/D板读取数据。drawpad.RunDraw();调用了另一类的成员函数进行画黑白方格相间的图。
我的思路是:在do-while循环中,(1)先调用画图函数,画黑白棋盘格——(2)转到线程中读取数据——回到do-while中重复(1)(2)这两步操作,直到循环退出,将刚才所读取的数据保存成TXT文件。如果正常的话,看到的现象应该是黑白方格图在屏幕上闪烁若干次,然后结束,闪烁的时间间隔应该是相等的。黑白方格图在屏幕上停留的时间是线程运行的时间,也就是读取数据的时间,读取的数目固定,每次时间应该是相等的。我现在看到的现象是,黑白方格图前几次闪的特别快,后几次感觉还正常。单步调试时,发现线程好象正常、但有时又不正常!问题出在哪呢,大家能帮我分析一下吗,只要解决,分好商量!

解决方案 »

  1.   

    drawpad.RunDraw();中的代码如下:
    void CDrawPad::RunDraw()
    {
        
    CPaintDC dc(this); // device context for painting
             Invalidate();
    //dc.SetMapMode(MM_HIMETRIC);//映射模式的设置
    CDC *memDC = new CDC;
    memDC->CreateCompatibleDC(&dc);
    CBitmap *memBmp = new CBitmap;//内存绘图
    CRect ClientRect;
    GetClientRect(ClientRect);
    memBmp->CreateCompatibleBitmap(&dc, ClientRect.Width(), ClientRect.Height());
    CBitmap *pOldBmp = memDC->SelectObject(memBmp);

    if((k%2)==0)
    DrawElement(memDC, ClientRect, TRUE);//DrawElement()这个函数的代码,下面给出了
    else
    DrawElement(memDC, ClientRect, FALSE);

    //把内存绘图拷贝到屏幕
    dc.BitBlt(ClientRect.left, ClientRect.top, ClientRect.Width(), ClientRect.Height(),
    memDC, 0, 0, SRCCOPY);

    memDC->SelectObject(pOldBmp);
    memDC->DeleteDC();
    delete memDC;
    memBmp->DeleteObject();
    delete memBmp;
    k++;
    }
    void CDrawPad::DrawElement(CDC *pDC, const CRect DrawRect, BOOL BlackFirst)//画黑白棋盘格图
    {
        if (!pDC)
    return;
        
    CBrush *pOldBrush = (CBrush*)pDC->SelectStockObject(WHITE_BRUSH);
    CPen *pOldPen = (CPen*)pDC->SelectStockObject(NULL_PEN);
    pDC->Rectangle(DrawRect);
    pDC->SelectStockObject(BLACK_BRUSH);
    CRect rcBlack(DrawRect.left, DrawRect.top, DrawRect.left + m_size0, DrawRect.top + m_size0);
    if (!BlackFirst)
    {
       rcBlack.OffsetRect(m_size0, 0);
    }
    while (rcBlack.top < DrawRect.bottom)
    {
    while (rcBlack.left < DrawRect.right)
    {
    pDC->Rectangle(rcBlack);
    rcBlack.OffsetRect(m_size0 + m_size0, 0);
    }
    rcBlack.left = DrawRect.left;
    rcBlack.top += m_size0;
    rcBlack.right = rcBlack.left + m_size0;
    rcBlack.bottom = rcBlack.top + m_size0;
    if (BlackFirst)
    {
    rcBlack.OffsetRect(m_size0, 0);
    }
    BlackFirst = !BlackFirst;
    }
    pDC->SelectObject(pOldPen);
    pDC->SelectObject(pOldBrush); //在屏幕中央画小红点部分
        pDC->FillSolidRect(DrawRect.right/2-5, DrawRect.bottom/2-5, 10, 10, RGB(255,0,0) );
    //画红点部分结束

    ReleaseDC(pDC);

    原来我放在void CDrawPad::RunDraw()中的代码是放在void CDrawPad::OnPaint()中的,除了Invalidate();这句。原来我是想在CVEPView::SampleSetup()中通过drawpad.Invalidate();触发画图的,结果出现不了黑白格子图交替出现的情况。别人告诉我:Invalidate触发重画只是发送WM_Paint消息,在此消息没有得到处理的时候,如果再有同样的消息到达,一律被抛弃。所以我就改成现在的情况了。我不知道还是不是Invalidate();的问题。谢谢大家了,欢迎给出意见!^-^
      
      

  2.   

    do{
           FlashCount++;   //启动画黑白棋盘格图
      drawpad.ShowWindow(TRUE);
      drawpad.RunDraw();
       //调用从A/D读取数据的线程
       gm_pThread = AfxBeginThread(&Thread_IO_InData,NULL);
        }while(FlashCount<FlashTotalCount);
    //AfxBeginThread是开启一个新的线程,你这样调用的话,会同时开启多个线程,而且主线程并没有中断(没有等待读取数据完毕)。
    //同时,在你的线程函数Thread_IO_InData中,你直接就调用pView->SampleData();
    //所以,同时开了多个线程以后,每个线程都会调用pView->SampleData();然后才是延时。
    //因此,最开始每次闪烁的间隔时间应该是创建新的线程,以及线程执行到pView->SampleData();
    //以后的时间,后面的间隔时间就与Delay()的时间有关了,不过也不是Delay指定的时间
      

  3.   

    不知道你为什么要开启线程,看你刚才说的思路:
    在do-while循环中,(1)先调用画图函数,画黑白棋盘格——(2)转到线程中读取数据——回到do-while中重复(1)(2)这两步操作,直到循环退出
    //应该是画完棋盘以后,转到线程读取数据,这个时候应该是等待数据读取完毕?然后才重复前面的调用,还是不需要等待就开启线程读取新的数据?