本帖最后由 VisualEleven 于 2013-08-09 12:21:02 编辑

解决方案 »

  1.   

    改用异步模式 试试看Serial Communications in Win32
      

  2.   

    //设定读超时
    TimeOuts.ReadIntervalTimeout=0;
    TimeOuts.ReadTotalTimeoutMultiplier=0.5;
    TimeOuts.ReadTotalTimeoutConstant=1;
    你好,发现更改读超时可以缓解界面卡的问题,需要设成很小才行,但是这样在while循环里读串口就太快了,并且串口给buff的总是0,我有一个自动应答的功能加了定时器来判断串口是否返回数据判断bReadStat是否为1,而buff被传进了0,bReadStat也是1,这不是我想要的,不知道说的清不清楚,帮忙看看吧,谢谢!
      

  3.   

    Sleep(1),while中地方任选会好。
    PS:楼主按钮是开线程启动的么?如果不是用线程的话,是会非常卡的。
    另外,如果楼主开了线程还卡的话,那么说明楼主电脑估计是单核的。
      

  4.   

    按说吧超时设大些就可以啊
    TimeOuts.ReadIntervalTimeout=50;
    TimeOuts.ReadTotalTimeoutMultiplier=50;
    TimeOuts.ReadTotalTimeoutConstant=100;把调用CreateFile的那段贴出来看看
      

  5.   

    }*/
    hcom=CreateFile(SerialName,GENERIC_READ|GENERIC_WRITE,
    0, NULL, OPEN_EXISTING,0, NULL);
    int t=GetLastError();
    if(hcom==INVALID_HANDLE_VALUE)
    { AfxMessageBox(_T("打开串口失败!"));
    return false;
    }
    else{
    //指定端口监测的事件集
    SetupComm(hcom,100,100); //输入缓冲区和输出缓冲区的大小都是100
    COMMTIMEOUTS TimeOuts;
    //设定读超时
    TimeOuts.ReadIntervalTimeout=1000;
    TimeOuts.ReadTotalTimeoutMultiplier=0.5;
    TimeOuts.ReadTotalTimeoutConstant=1;
    //在读一次输入缓冲区的内容后读操作就立即返回,
    //而不管是否读入了要求的字符。
    //设定写超时
    TimeOuts.WriteTotalTimeoutMultiplier=100;
    TimeOuts.WriteTotalTimeoutConstant=500;
    SetCommTimeouts(hcom,&TimeOuts); //设置超时
    DCB dcb;
    GetCommState(hcom,&dcb);
    dcb.BaudRate=(DWORD)BaudRate; //波特率为38400
    dcb.ByteSize=8; //每个字节有8位
    dcb.Parity=NOPARITY; //无奇偶校验位
    dcb.StopBits=ONESTOPBIT; //一个停止位
    PurgeComm(hcom,PURGE_TXCLEAR|PURGE_RXCLEAR);}
    return TRUE;
      

  6.   

    TimeOuts.ReadTotalTimeoutMultiplier=50;
    TimeOuts.ReadTotalTimeoutConstant=100;这个稍微设大点点按钮就有点卡了,而且我6楼说的那个功能跟读串口超时有关系,这两者感觉就冲突似的,超时设大了就卡,设很小又达不到那个功能,哎
      

  7.   

    感觉不像在两个线程中运行似的,是不是与线程中操作UI有关?在ClearCommError之前sleep(如50、100);
    ClearCommError(hcom,&dwErrorFlags,&ComStat);
    在ClearCommError之后 判断ComStat.cbInQue,如果超过欲读的字节数(如22)就读,否则继续while等待
    这样的话 读超时就可用可不用了
      

  8.   

    我用的是同步读串口的,无法判断ComStat.cbInQue。线程只是用来实时读取串口数据的,操作界面是通过点击按钮的。
      

  9.   

    我使用 CreateFile 、ReadFile WirteFile 来对串口进行操作,针对我的外设,超时时间设置要给大点,大于200ms 超时。
      

  10.   

    哪里讲过同步读串口 无法判断ComStat.cbInQue
      

  11.   

    界面线程读写慢速外设,如果超时比较大,或者死循环读写,或者界面线程Sleep时间比较长,就会出现卡界面的现象。线程理处理,要求和界面线程(主线程)通讯时,不能使用SendMessage这样的同步函数。
    否则同样会卡界面。
    当然界面线程,也不能挂起自己,比如和其他线程同步,共享锁,资源被锁住的时候,界面就会卡住。
      

  12.   

    MFC有许多函数调用了,SendMessage ,不能用于工作线程和主线程通讯。
    MFC不是多线程安全的。
    MFC 不能和CreateThread,乃至_beginthread,_beginthreadex一起很好的工作。
      

  13.   

    ReplaceSel 就是使用SendMessage 的函数之一。
      

  14.   

    你好,试了下,把所有用到ReplaceSel的地方都去掉了,超时改大了点按钮还是卡啊?这到底怎么解决呢?
    //设定读超时
    TimeOuts.ReadIntervalTimeout=1000;
    TimeOuts.ReadTotalTimeoutMultiplier=0.5;//改成100
    TimeOuts.ReadTotalTimeoutConstant=1;//改成500了
      

  15.   

     1)
    ExitThread(0);

    return 0;
    效果差不多,除非线程函数调用了别的函数;
    在那个函数里直接退出线程,否则没有必要使用ExitThread(0);2)while(true)
    这个线程没有推出条件,难道一直工作?
    3)
    每次只读22个字节数据,就刷新界面,是否刷新太快了??
    串口虽然慢,读22个字节还是很快的。
    4)
    AppendText在干啥???
    5)sizeof (buf) 是多少,每次只读22个字节,为何循环终止条件是i<sizeof (buf)
    6)BuildData(buff);做些什么???
    7)SetTime();做些什么???设置超时???
    8)点击按钮都干了啥????
      如果启动线程,那么点击两次,就会启动2个线程工作,每个线程,都无法退出。
     点击N此,会启动N个线程工作,这个问题如何解决????
    PS:
    以上这些问题,在你的代码里都看不出来,所以看不出哪里会卡界面,需要你自己检查一下!        
      

  16.   

    1)
    ExitThread(0);

    return 0;
    效果差不多,除非线程函数调用了别的函数;
    在那个函数里直接退出线程,否则没有必要使用ExitThread(0);//这个删了2)while(true)
    这个线程没有推出条件,难道一直工作?//因为想一直监控串口有没有数据返回所以用这个,没有退出条件
    3)
    每次只读22个字节数据,就刷新界面,是否刷新太快了??//因为串口返回的数据长度不同,但大部分是22就写死了,我不知道怎么根据数据长度来控制显示的长度。
    串口虽然慢,读22个字节还是很快的。
    4)
    AppendText在干啥???//这个是改变输出字符的颜色并显示在编辑框中
    5)sizeof (buf) 是多少,每次只读22个字节,为何循环终止条件是i<sizeof (buf)//这样写其实长度就是22,跟第三个问题一样。
    6)BuildData(buff);做些什么???//这个是一个对读出数据进行解析的函数
    7)SetTime();做些什么???设置超时???//这个是显示系统时间的
    8)点击按钮都干了啥????//点击按钮执行WriteFile()向串口发送指令,界面上只要点击发送指令的都卡。其他的不卡
      如果启动线程,那么点击两次,就会启动2个线程工作,每个线程,都无法退出。
     点击N此,会启动N个线程工作,这个问题如何解决????//启动线程只是打开串口的时候开启,只需要启动一次啊关闭线程的时候有关闭线程
    PS:
    以上这些问题,在你的代码里都看不出来,所以看不出哪里会卡界面,需要你自己检查一下!        
    问题都回答了,帮帮看看吧,问题在哪里
      

  17.   

    NT,2000,XP等系统窗口程序: 
    界面线程是两个,一个是主线程,一个是主线程的守护线程。
    ++
      

  18.   

    1 界面卡和读线程关系不大,问题在别处。
    2 这与读超时关系不大。建议读线程稍作改动
    while(true)
        {
            DWORD SIZE;
            COMSTAT ComStat;
            DWORD dwErrorFlags;
            memset(buff, 0, sizeof(buff));
            ClearCommError(hcom,&dwErrorFlags,&ComStat);
            if(ComStat->cbInQue < 22)////同步读串口,一样能判断ComStat.cbInQue
                continue;

            bReadStat= ReadFile(hcom,buff,22,&SIZE,NULL);TRACE1("hcom=%d",hcom);
            if(bReadStat)
            {
                    CString temp;
                    m_ctrlMyRichEdit.ReplaceSel(_T("\r\n"));
                    SetTime();
                    if(buff[0]==6||buff[0]==21)
                    {temp.Format(_T("%02X "),buff[0]);
                    AppendText((BYTE*)temp.GetBuffer(0),20,RGB(255, 0,0));    
                    }
                    else
                    {
                        for(int i=0;i< sizeof(buff);i++)
                        {
                            temp.Format(_T("%02X "),buff[i]);
                            AppendText((BYTE*)temp.GetBuffer(0),24,RGB(255, 0,0));            
                                                }   
                        BuildData(buff);
                    }
                    }
            PurgeComm(hcom, PURGE_TXABORT|
                PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);    
             
        }
      

  19.   

    读超时设置随便设置就行 但不能过小
    TimeOuts.ReadIntervalTimeout=50;
    TimeOuts.ReadTotalTimeoutMultiplier=50;
    TimeOuts.ReadTotalTimeoutConstant=100;
      

  20.   

    在我的电脑上 读线程同时向两个RichEdit、一个Edit写40k字节的数据,界面没感觉有什么影响。
    从别处找找看吧
      

  21.   

    找到问题了 bReadStat= ReadFile(hcom,buff,22,&SIZE,NULL);
    改成dwLength = ComStat.cbInQue ; 
    bReadStat= ReadFile(hcom,buff,dwLength,&SIZE,NULL);
    大小不能定死,但是不知道为什么不行。
    另外输出数据for(int i=0;i< dwLength;i++)
    {temp.Format(_T("%02X "),buff[i]);
    AppendText((BYTE*)temp.GetBuffer(0),24,RGB(255, 0,0));
    }  
    我用虚拟串口发送一串数据,点击按钮要等一下才能收到数据不知道为什么,连续点击按钮好几次才收到一条数据。设断点dwLength的值也在递增。
      

  22.   

    大小是能够定死的
    if(ComStat.cbInQue < ALENGTH)////同步读串口,一样能判断ComStat.cbInQue
                continue;
    这样的话就可以读取固定字节的数据。
    你的程序,一般说来每个循环只能读取1个或0个字节,线程刚切换进去可能多几个。最好在读之前判断一下虚拟串口也是串口,好的虚拟串口像串口一样,按照一定的速率发送数据。你在调试的时候数据让然会进来,dwLength增加也就顺理成章了。cbInQue是进入读缓冲区的数据嘛