想请教个问题,对于Delphi编程,如果对多个事件的处理过程中,都调用同一个用户自己编写的函数的话,假如第一个事件中正在调用function1函数,这时有第二个事件被触发,继而转向第二个事件处理过程中,如果第二个事件过程里面也调用function1函数的话,由function1函数计算的结果就不对。如果要是有多个事件,而且有可能会在第一个事件调用某一函数还未退出此函数的时候,第二个事件,又会调用这个函数的话,有什么解决办法吗?还是说,需要编写多个同样功能的function1函数,起不同名称,不同事件调用不同名称?类似下面代码:

解决方案 »

  1.   

    代码为: //××××××××××××××××××××××××××
    // CalCRC16用于计算CRC16校验码
    // 多项式公式为X16+X15+X2+1
    //××××××××××××××××××××××××××
    function CRC16(AData:array of Byte;AStart,AEnd:Integer):Word;
    const
      GENP=$A001;  //多项式公式X16+X15+X2+1(1100 0000 0000 0101)
    var
      crc:Word;
      i:Integer;
      tmp:Byte;procedure CalOneByte(AByte:Byte);  //计算1个字节的校验码
    var
    j:Integer;
    begin
      crc:=crc xor AByte;   //将数据与CRC寄存器的低8位进行异或
      for j:=0 to 7 do      //对每一位进行校验
      begin
        tmp:=crc and 1;        //取出最低位
        crc:=crc shr 1;        //寄存器向右移一位
        crc:=crc and $7FFF;    //将最高位置0
        if tmp=1 then         //检测移出的位,如果为1,那么与多项式异或
          crc:=crc xor GENP;
          crc:=crc and $FFFF;
      end;
    end;
    begin
      crc:=$FFFF;             //将余数设定为FFFF
      for i:=AStart to AEnd do   //对每一个字节进行校验
        CalOneByte(AData[i]);
      Result:=crc;
    end;
    //此过程为定时器定时3s的触发事件,事件中调用CRC16函数
    procedure TForm1.Timer1Timer(Sender: TObject);
      var
        incrc:WORD;begin  incrc:=CRC16(txBuffer,LOW(txBuffer),4-1);end;//按钮1的事件触发函数:里面调用CRC16函数
    procedure TForm1.Button1Click(Sender: TObject);
    var 
         sanF:WORD;
    begin
      sanF:=CRC16(rxBuffer,LOW(txBuffer),4-1);
    end;
    类似这样的代码
      

  2.   

    系统会为ontimer 和 buttonclick的消息进行排序,这里的crc16运算不是并发的,总能分出先后除非在线程中执行,须考虑线程安全性
      

  3.   

    可是如果ontimer消息调用crc16函数的还未退出的时候,触发了buttonclick事件,在buttonclick事件中再次调用crc16函数的时候,计算的值就是错的。请问这个是什么问题?
      

  4.   

    就你给的代码来看,Timer事件触发在执行过程中,是不会响应Btuuon.Click的,因此你的这个代码不存在重入问题,那肯定是其他地方有问题了,比如txBuffer在什么地方处理的,怎么处理的,等
      

  5.   

    哦,贴个我写的程序,上面的代码只是个说明问题的代码。
    程序中使用了,SPCOMM串口控件,定时器控件。定时器会每隔3s触发事件,进入Timer1Timer()过程利用SPCOMM的发送函数,通过串口将数据发出;同时下位机也会向串口发送数据,串口接收到数据时,SPCOMM就会进入Comm1ReceiveData()过程中,这个时候就会调用crc函数,但是计算的结果是错的。
    代码如下:function Managemessage(mbufferlength :WORD):word;
        var
        i,j:integer;
        zhengfu:shortint;    test1,test2:integer;    crccompare1,crccompare2:WORD;    aa:longint; begin
      crccompare2:=rxBuffer[mbufferlength-3];                //rxBuffer[]中最后几个字节数据位   CRC低字节,CRC高字节,$0A,$0D
      crccompare2:=(crccompare2 shl 8 )or rxBuffer[mbufferlength-4];  crccompare1:=CRC16(rxBuffer,LOW(rxBuffer),mbufferlength-4-1) ;  if crccompare1<>crccompare2   then   exit(0);end;
    procedure TForm1.Timer1Timer(Sender: TObject);
      var
        incrc:WORD;begin
      txBUFFER[0]:=DeviceAddr ;  txBUFFER[1]:=byte($01); {命令号}  txBUFFER[2]:=byte($00);  txBUFFER[3]:=byte($05);
      incrc:=CRC16(txBuffer,LOW(txBuffer),4-1);  txBuffer[4]:=byte(incrc);
      txBuffer[5]:=byte(incrc shr 8);  senddata(6-1);{调用发送函数}
    end;//接收数据事件处理
    procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
      BufferLength: Word);var  forDisplay: string[11];
    begin
       move(buffer^,pansichar(@rxBUFFER)^,bufferlength);
      if Managemessage(bufferlength)<>0 then
           showmessage('数据接收成功!');end;
      

  6.   

    function CRC16(AData:array of Byte;AStart,AEnd:Integer):Word;procedure CalOneByte(AByte:Byte); procedure TForm1.Timer1Timer(Sender: TObject);
      var
        incrc:WORD;begin  incrc:=CRC16(txBuffer,LOW(txBuffer),4-1);end;哦,贴个我写的程序,上面的代码只是个说明问题的代码。
    程序中使用了,SPCOMM串口控件,定时器控件。定时器会每隔3s触发事件,进入Timer1Timer()过程利用SPCOMM的发送函数,通过串口将数据发出;同时下位机也会向串口发送数据,串口接收到数据时,SPCOMM就会进入Comm1ReceiveData()过程中,这个时候就会调用crc函数,但是计算的结果是错的。
    代码如下:function Managemessage(mbufferlength :WORD):word;
    根据你所说的,你的参数应该就是指针传递,你用函数封好了,它还是对SPCOMM传递过来的BUFF进行处理的,所以,当存在重复调用的时候,结果应该不会正确的
    本人水平有限,对SPCOMM也不是很精通,觉得最直接的办法是先把指针的内容在ReceiveDATA中保存为非指针,再调用函数
    另外,3s对COM口发一个数据,这个周期有没有问题?得结合你自己的COM口设备 传输速度,和处理流程。个人觉得,如果在PC上对COM口这样控制的话,溢出或崩溃是很容易的事