procedure TReadPLUS.saveCheckData(nrow,ncol:integer;s:string);
var
    ip:integer;
    nplus1:integer;
    gw,dw:integer;
begin
  //if  WaitForSingleObject(Critical1,INFINITE)=Wait_Object_0 then
  //begin
//    inherited saveCheckData(nrow,ncol,s);    // skip error code
    if s[1]='E' then
    else begin
        gw:=ord(s[ckCOM_HEAD+2+1])-$33;
        dw:=ord(s[ckCOM_HEAD+1+1])-$33;
        if gw<0 then
          gw:=gw+256;
        if dw<0 then
          dw:=dw+256;
        nplus1 := 256*gw+dw;
    end;    ip:=fieldMatchArr[sysSetRecord.nCurFlow].svPOS[svREAD_PLUS_z];
    if s[1]='E' then begin
        pubclass.savethreadRecord(nRow*sysSetRecord.numCol+nCol,ip,'');
          inherited saveCheckData(1+sysSetRecord.region+nRow*sysSetRecord.numCol+nCol,ip,'');
    end
    else begin
        pubclass.savethreadRecord(nRow*sysSetRecord.numCol+nCol,ip,inttostr(nplus1));
          inherited saveCheckData(1+sysSetRecord.region+nRow*sysSetRecord.numCol+nCol,ip,inttostr(nplus1));
    end;
  //end;
  //ReleaseMutex(Critical1);
end;

解决方案 »

  1.   

    TReadPLUS= class(TCheckComThread)
      protected
          procedure reCalErrField;override;
          procedure saveCheckData(nrow,ncol:integer;s:string); override;
      end;
    procedure TCheckComThread.saveCheckData(nrow,ncol:integer;s:string);
    var
        sr:string;
        qTp:integer;
    //    rBk:rSaveCmd;
    begin
    //    1:&Aacute;÷&sup3;&Igrave;, 2-4:&frac14;&Ccedil;&Acirc;&frac14;&ordm;&Aring;,5-6:×&Ouml;&para;&Icirc;&ETH;ò&ordm;&Aring;,7-23:&Igrave;&otilde;&Acirc;&euml;, 24-33:&Ecirc;±&frac14;&auml;,>33: &Atilde;ü&Aacute;&icirc;&Atilde;&ucirc;
    //    &acute;&aelig;&Aring;&Igrave;&ETH;&Aring;&Iuml;&cent;    if length(s)=0 then exit;
        if s[1]<>'E' then begin
            // &frac14;&Oacute; 1+sysSetRecord.region &Ograve;&Ocirc;&Ccedil;&oslash;·&Ouml; &sup2;&raquo;&acute;&aelig;&Aring;&Igrave;&micro;&Auml;&Ccedil;é&iquest;&ouml;
            if nrow>sysSetRecord.region then
                qTp :=nrow-(1+sysSetRecord.region)
            else
                qTp :=-1;        with dmData.chkTable1 do begin   ///A
                append;
                fieldbyname('nFlow').asinteger :=sysSetRecord.nCurFlow;
                fieldbyname('nRec').asinteger :=qTp;
                fieldbyname('nField').asinteger :=nCol;
                fieldbyname('sMeterId').asstring :=sMeterId;
                fieldbyname('sTime').AsFloat :=now;
                fieldbyname('sCmdName').asstring :=sProcInfo;
                fieldbyname('sSaveDisk').asstring :=s;
                post;
            end;
        end;
    end;procedure TCheckComThread.Execute;begin     //lhf
         //InitializeCriticalSection(cs);     //EnterCriticalSection(cs);     VisualSwap;     //lhf
         //LeaveCriticalSection(cs);
         //DeleteCriticalSection(cs);
        {for i:=1 to 2000000 do
        begin
          if terminated then
            exit;
        end;}    //terminate;
        //free;
        //self:=nil;
    end;
    procedure TCheckComThread.VisualSwap;
    begin
        sCommInfo :='&Otilde;&yacute;&Ocirc;&Uacute;'+sProcInfo+'...';
        sCommInfo1 :='';
        Synchronize(dispQYStatus);
        DoComm;
        //waitfor();
    end;procedure TCheckComThread.DoComm;
    var
        i:integer;
        s:string;
    begin
        for i:=0 to sysSetRecord.numCol-1 do begin
            if Terminated then begin
                sCommInfo := chr(idThread+ord('A'))+'&Ccedil;&oslash;±&raquo;&Oacute;&Atilde;&raquo;§&Ouml;&ETH;&para;&Iuml;...';
                Synchronize(dispCommStatus);
                bErrBw := bErrBw+1;
                break;
            end;
            //' '=±í&raquo;&micro;
            if sysSetRecord.meterNumArr[idThread][i][1]=' ' then begin
                if sysSetRecord.sDefineReadWrite<> '' then begin
                    if i<> ord(sysSetRecord.sDefineReadWrite[2]) then
                        continue;
                end;
                sMeterId :=copy(sysSetRecord.meterNumArr[idThread][i],
                    sysSetRecord.meterAt+1,sysSetRecord.meterLen); //   ±í&ordm;&Aring;
    //            nMeterRow :=
                nMeterCol :=i;
                if sMeterId='' then
                    continue;
                s := sendCmdTo485(i);
                //writeln(hSaveEvent,s);
                //Flush(hSaveEvent);
                if WaitForSingleObject(Critical1,INFINITE)=Wait_Object_0 then
                begin
                try
                    saveCheckData(idThread,i,s);  // clear data if error
                except
                    ;
                end;
                end;            ReleaseMutex(Critical1);
                if s[1]='E' then
                   bErrBw := bErrBw+1;
            end;
        end;
    end;
      

  2.   

    procedure TCheckComThread.VisualSwap;
    begin
        sCommInfo :='&Otilde;&yacute;&Ocirc;&Uacute;'+sProcInfo+'...';
        sCommInfo1 :='';
        Synchronize(dispQYStatus);
        DoComm;
        //waitfor();
    end;
    procedure TCheckComThread.dispQYStatus;
    begin
        if WaitForSingleObject(Critical1,INFINITE)=Wait_Object_0 then
        begin
        frmInfo.InfoListView.Items[idThread].SubItems[0] :=sCommInfo;
        frmInfo.InfoListView.Items[idThread].SubItems[1] :=sCommInfo1;
        end;
        releasemutex(Critical1);
    end;
      

  3.   

    function TCheckComThread.sendCmdTo485(nMCol:integer):shortstring;
    var
        j:integer;
        s:string;
    begin
    //    sCmdIndex : integer;    //  &Atilde;ü&Aacute;&icirc;&ETH;ò&ordm;&Aring;
    //    sMeterId : shortstring; //   ±í&ordm;&Aring;
        //Ecount:=0;
        if sMeterId='' then begin
            result := 'E';
            exit;
        end;
        if frmcommand.errCkkBox1.Checked then begin
            sCommInfo := '&Otilde;&yacute;&Ocirc;&Uacute;&Oacute;&euml;±í'+sMeterId+'&Iacute;¨&ETH;&Aring;';
            Synchronize(dispCommStatus);
        end;
        dispRunTimeInfo;    for j:=1 to sysSetRecord.retry do begin
            s := DoComWith485;
            if s[1]<>'E' then begin            break;
            end
            else begin
                //Ecount:=Ecount+1;
                dispRunTimeInfo;
                sCommInfo := '['+char(idThread+ord('A'))+','+inttostr(nMCol+1)+
                    ']±í'+sMeterId+copy(s,2,20);
                if frmcommand.errCkkBox1.Checked then
                    Synchronize(dispCommStatus)
                else begin
                    if j=sysSetRecord.retry then
                        Synchronize(dispCommStatus);
                end;
                if j=sysSetRecord.retry then
                    if WaitForSingleObject(Critical1,INFINITE)=Wait_Object_0 then
                    begin
                try
                   pubclass.saveErrorInfo(sProcInfo+' '+sCommInfo);
                except
                    ;
                end;
                     end;
                ReleaseMutex(Critical1);
            end;
        end;
        //sysSetRecord.Errcount:=Ecount;
        result := s;
    end;
    function TCheckComThread.DoComWith485:shortstring;
        procedure minuFEFE(iL:integer);
        var
            i:integer;
        begin
            for i:=1 to iL do
                if CheckComClass.comRecvBuffer[idThread][i]=#$68 then begin// &frac14;&Oacute;FEFE 2bytes
                   CheckComClass.comRecvBuffer[idThread] :=
                     copy(CheckComClass.comRecvBuffer[idThread],i,iL);               break;
                end;
        end;
        function checkRecvValid(sr:string):shortstring;
        var
            iL:integer;
        begin
            result :='';
            if sr[1] <> #$68 then begin
                result :='&Icirc;&THORN;68H&Iacute;·&ETH;&Aring;&Iuml;&cent;';
                exit;
            end;
            if sr[9] <> cHeadCommand[sCmdIndex][3] then begin
                result :='&Oacute;&brvbar;&acute;&eth;&Atilde;ü&Aacute;&icirc;&ETH;&Aring;&Iuml;&cent;&acute;í&Icirc;ó';
                exit;
            end;
            iL:= ord(sr[10]);
            if sr[11+iL]<>pubclass.checkSum(copy(sr,1,10+iL)) then begin
                result :='&ETH;&pound;&Ntilde;é&acute;í&Icirc;ó&pound;&iexcl;';
                exit;
            end;
            if sr[12+iL]<>#$16 then begin
                result :='&frac12;á&Ecirc;&oslash;·&ucirc;&acute;í&Icirc;ó&pound;&iexcl;';
                exit;
            end;
        end;
    var
        sCmd,sErr:string;
        f,iHZP,i,iRecvL:integer;
        stB:tdatetime;
    //  {$IFDEF COM_DEBUG}
     stB11:tdatetime;
     sE:string;
    //  {$ENDIF}
    begin    iRecvL := 12+ord(cHeadCommand[sCmdIndex][4]);
        if iRecvL>cComBufferSize then
            iRecvL := cComBufferSize;    commId.PurgeOut;
        commId.Purgein;
        pubclass.CommWait(sysSetRecord.SzhenDelay,false);
        sCmd :={#$fe+#$fe+}CheckComClass.CreateCommandStr(sCmdIndex,sMeterId,sGetSendData);
    //  {$IFDEF COM_DEBUG}
        stB11 := Now;
    //  {$ENDIF}// ver1.32 OLD:
        if WaitForSingleObject(CriticalW,INFINITE)=Wait_Object_0 then
        begin
        for iHZP:=0 to length(sCmd)-1 do begin  // 2001.11.29
           commId.Write(sCmd[1+iHZP],1);
           sleep(sysSetRecord.FDelayTime);
        end;
        end;
        ReleaseMutex(CriticalW);
    // ver1.33 NEW:  2002.2.5
        stB := Now;//  {$IFDEF COM_DEBUG}
    //DEBUG_ROW := 5;
        sE:=inttostr(trunc(abs(24*60*60*1000*(now-stB11))));//  {$ENDIF}    //  &Oacute;&Atilde;&Oacute;&Uacute;&frac14;ì&sup2;é&Ecirc;±&Ouml;&Oacute;
        CheckComClass.getTimeOfRecvStr(idThread);  // &frac12;&micro;&micro;&Iacute;&Ecirc;±&frac14;&auml;&Icirc;ó&sup2;&icirc;{$IFDEF COM_DEBUG}    DEBUG_ROW := 6;
        DEBUG_XXML('send...',sCmd);
    {$ENDIF}
        if CommDelay(sysSetRecord.type1,sysSetRecord.SDelayTime,iRecvL) then begin
    //        commId.read(CheckComClass.comRecvBuffer[idThread][1],iRecvL); // &frac14;&Oacute;FEFE 2bytes
    //        minuFEFE(iRecvL); // &frac14;&Oacute;FEFE 2bytes  2001.11.29
    {$IFDEF COM_DEBUG}
            DEBUG_ROW :=7;
            DEBUG_XXML('recv...',copy(CheckComClass.comRecvBuffer[idThread],1,iRecvL));
    {$ENDIF}
            sErr := checkRecvValid(CheckComClass.comRecvBuffer[idThread]);
            if sErr<>'' then
               result :='E'+sErr
            else begin
               pubclass.CommWait(1500,false);
               result :=' '+copy(CheckComClass.comRecvBuffer[idThread],1,12+ord(cHeadCommand[sCmdIndex][4]));
            end;
        end
        else begin
    {$IFDEF COM_DEBUG}
            DEBUG_ROW :=7;
            iRecvL := commId.InQueCount;
            if iRecvL>0 then begin
               commId.read(CheckComClass.comRecvBuffer[idThread][1],iRecvL);
               DEBUG_XXML('rev='+inttostr(iRecvL),copy(CheckComClass.comRecvBuffer[idThread],1,iRecvL));
            end
            else
               DEBUG_XXML('recv=0',' ');
    {$ENDIF}
            if frmcommand.errCkkBox1.Checked then begin
               sCommInfo :=sMeterId+' esc:'+sE;
               Synchronize(dispCommStatus);
            end;
            result :='E&Icirc;&THORN;&Oacute;&brvbar;&acute;&eth;';
        end;
    end;
      

  4.   

    //类的定义type
      TCheckComThread = class(TThread)
      private
        bErrBw:integer;
        sCommInfo :shortstring;
        sCommInfo1 :shortstring;
        sProcInfo:shortstring;
        sCmdIndex : integer;    //  &Atilde;ü&Aacute;&icirc;&ETH;ò&ordm;&Aring;
        sMeterId : shortstring; //   ±í&ordm;&Aring;
        nMeterCol:integer;  //  ±í&Icirc;&raquo;
        commId:TComm32;
    //    iRunIndex :integer;  // &Ocirc;&Euml;&ETH;&ETH;&Igrave;á&Ecirc;&frac34;·&ucirc;&ETH;ò&ordm;&Aring;// {$DEFINE COM_DEBUG}
    {$IFDEF COM_DEBUG}
        DEBUG_ROW :integer;
        procedure DEBUG_XXML(sL,sCmd:shortstring);
        procedure DEBUG_dispQYStatus;
    {$ENDIF}
        procedure dispRunTimeInfo;
        function CommDelay(nDelay,bDelay,nRecvNum:integer):boolean;
        procedure DoVisualSwap;
        procedure dispCommStatus;
        procedure dispQYStatus;
        procedure threadDone(Sender: TObject);
        function DoComWith485:shortstring;
        function sendCmdTo485(nMCol:integer):shortstring;
        procedure refreshParaInfo;
    //    procedure saveWriteInfo(nrow,ncol:integer;s:shortstring);
      protected
        procedure reCalErrField; virtual;
        procedure Execute; override;
        procedure VisualSwap;
        function sGetSendData:shortstring ;virtual;
        procedure DoComm; virtual;
        
        // s:shortstring  -> string
        // s:shortstring  -> string
        // s:shortstring  -> string
        procedure saveCheckData(nrow,ncol:integer;s:string); virtual;
      public
        idThread:integer;
        constructor Create(comm32:TComm32;Index,nCmd:integer;sCmdInfo:string);
      end;  TReadTime = class(TCheckComThread)
      protected
    //    function sGetSendData:shortstring; override;
        procedure saveCheckData(nrow,ncol:integer;s:string); override;
      end;  TSetTime = class(TCheckComThread)
      protected
        function sGetSendData:shortstring; override;
      end;  TReadPreiod = class(TCheckComThread)
      protected
    //    function sGetSendData:shortstring; override;
        procedure saveCheckData(nrow,ncol:integer;s:string); override;
      end;  TWritePreiod= class(TCheckComThread)
      protected
        function sGetSendData:shortstring; override;
      end;  TReadPower= class(TCheckComThread)
      protected
        procedure reCalErrField;override;
        procedure saveCheckData(nrow,ncol:integer;s:string); override;
      end;  TWriteZERO= class(TCheckComThread)
      protected
        function sGetSendData:shortstring; override;
      end;  TWriteRESV= class(TCheckComThread)
      protected
        function sGetSendData:shortstring; override;
      end; TWritePOWER= class(TCheckComThread)
      protected
        function sGetSendData:shortstring; override;
      end;  TReadPLUS= class(TCheckComThread)
      protected
          procedure reCalErrField;override;
          procedure saveCheckData(nrow,ncol:integer;s:string); override;
      end;
      

  5.   

    TReadPLUS继承于TCheckComThread,TCheckComThread继承于TThread,TCheckComThread和TReadPLUS都有saveCheckData方法,建立TReadPLUS线程示例后,进入execute过程中执行,在execute过程中调用DoComm过程进行处理.
      

  6.   

    长篇大论,没人愿看!多线程串口读写,一般使用数据包通讯方式,
    可以用一个子程序,处理发送一个数据包,在规定时间内等待读取应答数据包
    这个子程序,必须是不能重入的,即多个线程不能同时调用,用同步对象控制
    读取应答数据包应该用异步读取(重叠操作),或在循环读取中加入Sleep()适当延时,
    不要不停读取,否则会造成系统负荷过重我想你的错误可能是发送后没有等待应答,这样可能发送了多个数据包,多个下位机同时应答数据,造成应答数据错误,而你的检测读取数据没有正确处理这种异常造成的。
      

  7.   

    现在看来可能是串口的问题,每个线程中,循环向串口发送30次命令,串口的输入缓冲区中只能放下一此的数据,每次发送命令之前,会用purgecomm清空串口的输入和输出缓冲区,但是调用时没有判断purgecomm返回值,然后就又向串口发数据,我想可能这时串口有可能死掉。源代码挺长,没办法全贴出来。唉,这个问题搞了好几天了也没搞定,郁闷呀!