我爱builder

C++Builder 程序员博客

  请大家看看下面代码(csdn的朋友提供的,具体在哪拷贝的不记得了)

//以下是读串口方法中的部分代码
  ………………
  clock_t  start;
  start=clock();
  int i=0;
  for(;;) 
  {
          ClearCommError(idComDev,&dwErrors,&lpCommStat);//关键是这行代码
          i++;
          if  (dwErrors||  lpCommStat.cbInQue) /*  byte  received  or  error  ?  */ 
          {
              break;
          }
          else  if(clock()-start>1000) /*  time  out  4  clock  ticks  */
          {
              *ErrorNumber  =  -3;
              return(0);
          }
  }
  ………………
    在我单步调试的时候,ClearCommError函数每次都执行得很顺利,一次就能通过,并得到缓冲区的字节数lpCommStat.cbInQue不为0
    而如果去掉所有断点,直接运行后,通过返回的计数器值(即代码中的i)发现只有很少次能顺利执行,绝大部分时候ClearCommError函数要重试几万少也要几千次才能得到缓冲区字节数。。导致我读串口的速度很慢很慢。
    翻来覆去调了一天了,请朋友们帮帮我!谢谢了

谢谢楼上的

代码中给出的1秒重试算不算认为延时?我再去查查看

另补充:

发现发送一串字符后,都是接收第一个字节时延时较长,实验的结果,第一个字节接收延时828ms,其他字节接收在15ms和16ms两个值之间浮动

可以设置一下串口设置的超时参数,比如100毫秒。

to:Turntogo

打开串口时进行了设置

COMMTIMEOUTS  timeouts;

//………………

  timeouts.ReadIntervalTimeout=100; 
  timeouts.ReadTotalTimeoutMultiplier=3000; 
  timeouts.ReadTotalTimeoutConstant=3000; 
  timeouts.WriteTotalTimeoutMultiplier=3000; 
  timeouts.WriteTotalTimeoutConstant=3000; 
  if(!SetCommTimeouts(idComDev,&timeouts)) 
          return  (HANDLE)-3; 

for(;;) 
  {
          Application->ProcessMessages();
          ClearCommError(idComDev,&dwErrors,&lpCommStat);//关键是这行代码
          i++;
          if  (dwErrors||  lpCommStat.cbInQue) /*  byte  received  or  error  ?  */ 
          {
              break;
          }
          else  if(clock()-start>1000) /*  time  out  4  clock  ticks  */
          {
              *ErrorNumber  =  -3;
              return(0);
          }
          Application->ProcessMessages();
  }

楼主这段代码放在线程里面就不会有什么问题了。

楼上的建议应该是不错的,我也考虑过线程,不过由于时间关系我不能深入学习
现在使用Sleep()函数解决延时问题了,先结贴,谢谢了

  • Filed under: C++ Builder
  • 我的代码是这样的
        Variant  v_application  =  CreateOleObject("Word.Application"); 
        v_application.OlePropertySet("Visible",true); 
        Variant  v_document  =  v_application.OlePropertyGet("Documents"); 
        v_document.OleProcedure("Open","c:\\Windows\\desktop\\zbc.doc"); 
    前面加上了 
      #include  <comobj.hpp> 
      #include  <utilcls.h>
    但不知道为什么还是出现  Debugger  Exception  Notification的错误  Project  Project1.exe  raised  exception class EOleSysError with message '发生意外。’ Process stopped.  Use Stp or Run to continue. 

    [color=#FF0000][/c:\\Windows\\desktop\\zbc.doccolor]

    我测试下

    代码应该是没有问题的,你确保你的文档doc在这个路径下,如果不在这里

    就会出现你那样的错误,另外记得用完了要Quit

    若改成当前目录下
    是不是这样v_document.OleProcedure("Open","\\operate.doc");

    嗯,是的,那样的话doc文件应该和你的bpr,exe文件都是在同1目录下

    word文档的路径是没关系的,
    没必要拷到程序目录下。

    我把word放到bpr,exe文件都是在同1目录下了,然后改为v_document.OleProcedure("Open","\\operate.doc");
    但是还有错误,好像是在 <utilcls.h>中,还有什么可能性出现这种错误

    C:\Documents and Settings\Administrator\桌面
    查看一下你的路径,你可以到到其他地方实验一下,代码是没有问题的。桌面上可能是你的路径没有设置对

    问题还没解决,希望大家继续帮助
    Variant v_application = CreateOleObject("Word.Application");
    v_application.OlePropertySet("Visible",true);
    Variant v_document = v_application.OlePropertyGet("Documents");
    v_document.OleProcedure("Open","\\operate.doc");
    我的名为operate的word文件 和bpr,exe文件都是在桌面的同一文件夹下
    运行时还是出现发生意外的错误。

    你可以这样弄的嘛,,先在你固定的路径下建个word文档,比如C盘下建立1.doc

    v_document.OleProcedure("Open","C:\\1.doc");

  • Filed under: C++ Builder
  • 如题 ~~

    打印什么内容?还是excel吗?上次不是搞定了吗

    上次是搞定了~~打印,但默认是纵向的打印
    但我的表格是横向的,所以就又来问了~~
    顺便问一下能不能选打印机啊~~
    哎,刚刚出去了一下

    试试用"PrintPreview"替代"PrintOut",这样就可以选择打印模式和打印机了。

    好像  xlLandscape 不行~~

    我的office2007
    是不是和版本有关系~

    我的也是2007,PrintPreview不起作用,应用挂起了。怀疑可能是后台运行的原因。

    哎~~不过主要问题解决了~~
    忘了结帖了~~~今天才发现~~
    各位不好意思了~~~

    追加分数

    yuanreid 预览有进展要PM我啊~~

  • Filed under: C++ Builder
  • ADODataSet1    主表,主关键字ID
    ADODataSet2    从表,ProjectID跟主表ID对应,记录较多,每次只显示 ProjectID==ID的记录

    DBGRID1显示主表
    DBGRID2显示从表
    如何关连这两个表?

    select * from 主表,从表 where ID =ProjectID
    再放两个ADO控件对应DBGRID就行了
    DBGRID1对应主表字段,DBGRID2对应从表字段,
    ADOQuery1->Active =false;
    ADOQuery->SQL->Clear();
    ADOQuery1->SQL->Add("select * from 主表,从表 where ID =ProjectID ");
    ADOQuery1->Open() ;//打开

    DBGRID1的 datesource->dataset用ADOQuery

    引用 3 楼 xjq2003 的回复:
    DBGRID1的 datesource->dataset用ADOQuery
    对的

    一种是在ADOQUERY中的MASTER中设置一下.(就是二个数据表都为打开)

    别一种,你显示主表,选中一条,触发ONCLICK事件时,你把相关的从表记录打开一下(最好是双击触发)

    以上说的都不好!
    试好了,很简单的:
      从表的ADODataSet2的DataSource属性要指向ADODataSet1的DataSource1,
                        MasterField设成 ID–ProjectID,
    就这样,就好了.

  • Filed under: C++ Builder
  • 我现在可以访问网络上共享的一个文件夹,可以在那个文件夹增加,删除,但是就是无法执行这个文件夹中的文件(.exe或.bat),不可以在本机上运行它,要在网络上自动运行,如何实现,谢谢!

    不可以的
    因为我在Windows下都不能直接运行,提示"UNC路径不支持。。。。。"

    这里不是黑客论坛

    用WMI,写入注册表里的启动项,远端机器重启动就可以运行了。

    楼主想远程执行它,这就变成了黑客了,要用"黑客技术",
    普通技术无人为力,在这里问是缘木求鱼.

    在别人的机器上运行可执行文件?  普通权限应该不行吧。。嘿嘿

  • Filed under: C++ Builder
  • SDK30001->Connect(0,false,720,576); 或者SDK30001->Connect(0,true,720,576); 我用BCB写的主程序在调用Connect函数的时候 都弹出project admin.exe raised exception class EDivByZero with message 'Division by zero'.Process stopped.

    我用delphi实验了下,用的是
    SDK30001.connect(0,false,720,576)
    是没有问题的
    可是在BCB中用到了SDK30001->connect(0,false,720,576)就出现问题了

  • Filed under: C++ Builder
  • 调用ExcelApplication进行分组统计是这样写的:
    Range.OleFunction("Subtotal",5,xlSum,field,True,False,True);

    其中的field参数是一个列数组成的数组,但是我在前面这样赋值:
    int field[2]={6,7};
    得到的结果与
    Range.OleFunction("Subtotal",5,xlSum,6,True,False,True);
    相同,只对第6列汇总

    请高人指点

    谢谢楼上的

    继续等待

    不让它沉下去ⷾ up

    有人吗?

    作个记号,等回了家再回答你。

    引用 7 楼 ccrun 的回复:
    作个记号,等回了家再回答你。

    期望中~~

    如能解决,送一百分。。(CSDN人气如此差留着也没用)

    for(int i=5;i <6;i++) //这样用笨点的办法可以实现不?
      Range.OleFunction("Subtotal",5,xlSum,i,True,False,True);

    引用 9 楼 jone7319 的回复:
    for(int i=5;i <6;i++) //这样用笨点的办法可以实现不?
      Range.OleFunction("Subtotal",5,xlSum,i,True,False,True);

    我也试过,这样就会变成两个分类汇总,两行汇总数据

    是不是想将两个分类汇总后再汇总到一起?
    然后再合成一下试一试呗

    引用 11 楼 yt31109 的回复:
    是不是想将两个分类汇总后再汇总到一起?
    然后再合成一下试一试呗

    用不着这么麻烦吧,VB直接实现的代码我都有,就是转成BCB后的数组不知怎么处理

    引用 7 楼 ccrun 的回复:
    作个记号,等回了家再回答你。

    等你啊

  • Filed under: C++ Builder
  • 问题是这样的:
    有两个文本文件num.txt和name.txt一个是学号,一个是姓名。
    格式都是一个号码(姓名)一个'\n'(回车)。
    最后生成是结果是
    学号空格姓名再一个回车。
    215401 李二
    215402 张三

    要求用TStringList 谢啊。

    如果学号和姓名一一对应的话。

    C/C++ code
    TStringList *num = new TStringList; TStringList *name = new TStringList; TStringList *ret = new TStringList; num->LoadFromFile("num.txt"); name->LoadFromFile("name.txt"); for (int i=0;i<num->Count;i++) { ret->Add(num->Strings[i] + " " + name->Strings[i]); } ret->SaveToFile("ret.txt"); delete num,name,ret;

    成功,谢谢楼上的aniven

    ai

  • Filed under: C++ Builder
  • TADOConnection *ADOConnection1;
        TADOQuery *ADOQuery1();
        TDataSource *DataSource1;
        TADOStoredProc *ADOStoredProc1;
        TADOTable *ADOTable1;
        TADODataSet *ADODataSet1;
        ADOConnection1->ConnectionString="Provider=SQLOLEDB.1;Password=11111131;Persist Security Info=True;User ID=sa;Initial Catalog=test;Data Source=LIHONGBIN1;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=CE163D7937874F9;Use Encryption for Data=False;Tag with column collation when possible=False";
        ADOConnection1->LoginPrompt=false;
        ADOConnection1->KeepConnection=true;
        ADOTable1->Connection=ADOConnection1;
        ADOTable1->TableName="mytest";

    我这样写的话ADOConnection1->ConnectionString这里好象没达到效果 请问该怎么改呢?

    BCB  555

    加入:ADOConnection1->Open(); 或ADOTable1->Active = true;

    TADOQuery *ADOQuery1();

    Do you know what does this mean?

    Create a function named ADOQuery1,And Return TADOQuery *.

    And Also you should do like anmi_yang said,

    Add ADOConnection1- >Open(); or ADOTable1- >Active = true;

  • Filed under: C++ Builder
  • 还未解决;
    http://topic.csdn.net/u/20080919/15/62ae164e-90bf-4a36-870f-450050ea71b0.html

    插入与删除不在一个线程操作
    所以插入一般要比删除快

    当进行插入几条数据后,会出现非法的指针错误

    请问如何保护起来?
    能具体点吗? 有点急啊

    MSDN
    Critical Section Objects

    #include <SyncObjs.hpp>

    TCriticalSection *cs;

    cs=new TCriticalSection();

    cs->Enter();
    //这里放被保护的代码
    cs->Leave();

    随手贴以前的例子一个:

    typedef enum
    {
        rsIdle=0,    //空闲,表示待处理
        rsBusy=1,    //忙,正在被处理
        rsOver=2,    //已结束
        rsError=3,    //出错
        rsCancel=4,  //已取消
        rsPause=5    //暂停
    }TReqState;      //客户请求的状态

    class TClientReq
    {
    private:
        TReqState  m_ReqState;
        TCriticalSection *cs;
        TReqState  getReqState()
        {
            TReqState ret;
            cs->Enter();
            ret=m_ReqState;
            cs->Leave();
            return ret;
        };
        void      setReqState(TReqState rs)
        {
            cs->Enter();
            m_ReqState=rs;
            cs->Leave();
        };
    public:
        __property TReqState ReqState = { read=getReqState, write=setReqState};//请求的当前状态
        __fastcall TClientReq()
        {
            cs=new TCriticalSection();
            ReqState=rsIdle;
        };
        __fastcall ~TClientReq()
        {
            delete cs;
        };
        //后面还有些代码,无关,所以没贴
    }

    请问楼上,你说的这个保护起来,是否是存一条数据,待删除了,再存一条数据,再删除
    我这里存储比删除要快,所以可能会在缓冲区积累数据

    保护是针对多线程访问共享内存或变量的——
    把你最终插入和删除的代码贴下看看?

    要不我发给你   
    你帮我看看,行不?

    你的邮箱多少?

    whomin@gmail.com

    我已发送到你的邮箱,帮忙看看错在哪

    //插入数据
    bool __fastcall DataBuffer::Insert(int nType,void* pData)
    {
    cs->Enter();
        BufNode *pNewNode;
        //分配节点空间
        pNewNode= new BufNode() ;  //读入数据
        pNewNode->pData = pData;
        pNewNode->nType = nType;
        //修改最后节点位置
        m_pLast->pNext = pNewNode;
        m_pLast = pNewNode;
        //SetFinished();//释放内存
    cs->Leave();
        return true;
    }

    //删除节点
    bool __fastcall DataBuffer::Delete(BufNode *pDel,BufNode *pParent)
    {
    cs->Enter();
        if(GetSize()>0)
        {
            if(pDel == m_pLast)
            {
                m_pLast = pParent;
            }
            pParent->pNext = pDel->pNext;
            //释放内存
            if(pDel)
            {
              if(pDel->nType == 3) //暂态数据
              {
                    DataTrst *Tdata = NULL;
                    Tdata = (DataTrst *)(pDel->pData);
                    delete Tdata;
                    Tdata = NULL;
              }
              delete pDel;
              pDel = NULL;
            }
        }
    cs->Leave();
        return true;
    }

    为什么需要加保护呢?因为线程的运行是由系统调度自动完成的,具有一定的不确定性。
    如果不加保护的话,假想一线程在执行插入数据的同时、另一线程在删除节点,可能会产生下面的时序,你自己分析下就会发现可能出现问题了:
    1.删除线程: if(pDel == m_pLast)  //如果此时删除的刚好是最后一个节点
    2.插入线程: m_pLast->pNext = pNewNode;
    3.插入线程: m_pLast = pNewNode;
    4.删除线程:    {m_pLast = pParent;}  后面接的是删除pDel数据
    结果就是插入的数据丢了
    如果第3步、第4步的时序反过来,则m_pLast指向了一个并未加入到链表的数据(因为删除pDel就是删掉之前的m_pLast),以后就会弹异常了——

    还可能有其他地方存在问题,比如m_nCount变量应该是需要保护的,自己分析加调试看看吧

    赞一个

    你说的有道理
    我也曾试过,加入cs->Leave();
    但还是不行

    具体的还是只有自己去调试看看了,多加些异常捕获点吧

    不知道我那样的设计结构是否合理

    呵呵,其实我一般不用链表,维护起来麻烦点,直接用TThreadList不一样可以实现同样目的?它本身的Add、Remove都是安全的,也是可以存储对象的。

    你可以加我吗、?Q聊 253707481

    上班在呢,QQ 被禁止了,再说我n久没用QQ了,号码都忘记了——

    哦,还是挺谢谢你的
    这个贴我结了,我给你发消息吧

  • Filed under: C++ Builder
  • 类别

    最新

    标签

    链接


    存档