我做了一个对话框程序,它的主要功能是向串口不停的收发数据,因为数据量太大,以至于把程序最小化后不能恢复过来(此程序经常占用CPU 95 % 以上)。所以我决定使用多线程,让一个线程来负责串口通信,让主线程进行数据处理。在没有使用多线程的时候,我的思路是这样的。
有一个大的for循环
for(i...)
{
  ...串口通信;  ...数据处理;
}
按照这个思路我已经做好了程序。
现在我使用多线程技术,开了一个辅助线程,让辅助线程进行串口通信,主线程进行数据处理。但这样做带来一个问题,因为在每轮for循环里面,数据处理必须要等串口通信完成才行(我使用WaitForSingleObject(g_Event.m_hObject, INFINITE);),而每轮的串口通信数据量又特别大,这就导致主线程每轮都要等很长时间,那就使得“把程序最小化后不能恢复过来”。请问该怎么解决?
是要开两个辅助线程,一个进行串口通信,一个进行数据处理么?这样做,我要对原程序做较大的修改,比较复杂。如果依然仅开一个辅助线程,让这个辅助线程完成后通过消息通知主线程,应该怎么做啊?能不能在我的原来的大for循环的结构里面做小小修改就可以啊?谢谢!

解决方案 »

  1.   

    你可以:
    WaitForSingleObject(g_Event.m_hObject, 0);
    没有信号就继续别的事情,过段时间再查询一下。或者线程里数据接收完成向界面线程发送一个消息。
      

  2.   

    发送一个消息就可以,不要用SendMessage,用PostMessage
    参考:
    http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=435
      

  3.   

    Mackz(在相互),你的方法WaitForSingleObject(g_Event.m_hObject, 0);
    实际上是不行的,for(i...)
    {
      ...串口通信;  WaitForSingleObject(g_Event.m_hObject, 0);
      ...数据处理;
    }如果这样,就会在没有等到串口通信完成就进行数据处理了。这样是不行的。谢谢你!
      

  4.   

    laiyiling(陌生人 V3.0),
    我发现使用消息的话,会破坏for大循环。其实我这个for大循环是很复杂的,把串口通信部分用一个辅助线程来处理还是比较容易的,对原来的程序修改不大。如果要改成辅助线程发消息给主线程,那么对原来的代码改动很大。有没有对for大循环改动不大的方法啊?谢谢你!
      

  5.   

    for(i...)
    {
      ...串口通信;  WaitForSingleObject(g_Event.m_hObject, 0);
      if(hasData)
      {
       ...数据处理;
      }
    }
      

  6.   

    GoldenSword(金错刀)
    使用 if(hasData)也不行,因为那样就会进入循环的下一轮,这样也会把数据处理的顺序搞错。我想问问,有没有这样的wait,在主线程里面使用它,既可以让主线程停在那里不动,有可以让主线程不僵?
      

  7.   

    回复人: south2000(south2000) ( ) 信誉:100  2005-11-11 08:51:00  得分: 0  
     
     
       GoldenSword(金错刀)
    使用 if(hasData)也不行,因为那样就会进入循环的下一轮,这样也会把数据处理的顺序搞错。我想问问,有没有这样的wait,在主线程里面使用它,既可以让主线程停在那里不动,有可以让主线程不僵?
      
     
    ===========================================这样不会进入循环下一轮的,只有处理完成后线程才会继续往下走,你可以试试看。如果想让程序继续向下走的话,就用 PostMessage(),这样不会阻塞线程
      

  8.   

    建立两个全局布尔量。一个bDataCome表示是否有数据到来,一个bDataDealed表示是否数据是否处理完毕。bDataCome初值为false,bDataDealed初值为true.当辅助线程中收到数据时,置bDataCome为真,当bDataDealed为假时,辅助线程暂停数据的收发,在主线程中,当bDataCome为真时,开始处理数据,处理完毕置bDataCome为假,bDataDealed为真
      

  9.   

    最好的办法是另开一个线程来处理for循环
      

  10.   

    38062708,谢谢你。
    你说的方法,好像还是不行,我试过了。现在我写了一个简单的程序,这里说出它的步骤。
    1。做了一个Test的对话框程序,在上面放了一个按钮
    2。在.cpp文件里面
    CEvent g_e;
    UINT Thr(LPVOID pParam)//线程函数
    {
    Sleep(10000);
    g_e.SetEvent();
    return 0;
    }BOOL CTestDlg::OnInitDialog()
    {
            ......
            AfxBeginThread(Thr, NULL);
            return TRUE;  // return TRUE  unless you set the focus to a control
    }
    void CTestDlg::OnButton1() 
    {
    // TODO: Add your control notification handler code here
             int i;
    WaitForSingleObject(g_e.m_hObject, 0);
    i=1;
    i=2;
    i=3;
    }
    在WaitForSingleObject这句设置断点。发现,单步运行时候,根本没有任何等待时间,就会运行到i=1;处,再单步,变量i就给赋值1了。我如果用WaitForSingleObject(g_e.m_hObject, INFINITE);
    单步运行,确实会在WaitForSingleObject等待10秒钟,
    而直接运行(非调试),点击按钮主程序会出现僵的情况。我实际希望的情况是,在wait处等10秒,而主程序有不僵。
    jjiaming(阿熊),也谢谢你,不知道你对我现在的说法是否很清楚,请帮助,谢谢!
      

  11.   

    WaitForSingleObject(g_e.m_hObject, INFINITE);这样才可以
      

  12.   

    38062708,我已经用 INFINITE了出现了程序僵住的情况。
      

  13.   

    for(i...)
    {
      ...串口通信;  ...数据处理;
    }
    按照这个思路我已经做好了程序。
    ===========================================应该适当让cpu休息
    在串口通信中使用sleep(10),你自己调试吧。
    我就写过串口程序,适当加sleep,cpu会空闲很多,而且比没加处理速度基本一样。
      

  14.   

    回复人: south2000(south2000) ( ) 信誉:100  2005-11-11 08:51:00  得分: 0  
     
     
       GoldenSword(金错刀)
    使用 if(hasData)也不行,因为那样就会进入循环的下一轮,这样也会把数据处理的顺序搞错。我想问问,有没有这样的wait,在主线程里面使用它,既可以让主线程停在那里不动,有可以让主线程不僵?
      ===============================
    在主线程中使用wait 而不僵是不可能的。
    只能使用
    peekMessage
    具体你查查相当于vb中的DoEvent,使进程可响应消息(在主线程使用Wait,会阻塞主线程)
    在主线程组塞,发PostMessage是不起作用的,主线程根本不能响应,让主线程停下来而又不组塞消息唯一办法使用windows 消息循环PeekMessage你查查Msdn吧,我没时间给你贴代码了。
      

  15.   

    test2002(test2002),你说的方法,我也试过了,还是不行。我在上面写了一小段代码,我觉得与串口通信的意思差不多,你能看看么?
      

  16.   

    while(1)
    {
    if(m_bReceiveComplete|| m_bCancel)//接收完成或取消接收则跳出循环
    break;
    else
    {
                      //进入消息循环,使主线程序响应Windows 消息
    while(PeekMessage(&msg,0,0,0,PM_REMOVE))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }

    }
             //让主线程休息,可自己调节时间。
    Sleep(1000);
    }