我有一个线程类,里面有一个数组变量(在线程内定义的),在线程create的初始化数组,在exectue里赋值
我实例化这个线程(两个以上实例)后,发现这个数组变量的值混乱了,数组里有赋值的,中间有为零的(初始化状态)!如果只运行一个实例,则数组都大于零。我看书上说,线程的局部变量是跟随实例的,在我这里怎么变成公共变量了?????
为什么?怎么解决?

解决方案 »

  1.   

    线程局部存储TLS 要用专门的一套机制才行 如TlsAlloc...
    估计你没完全搞清楚 不好乱用
      

  2.   

    代码肯定有点问题,我这边测试正常!type
      Ta = class(TThread)
        arr: array[0..1] of Byte;
        constructor Create; reintroduce;
        procedure Execute; override;
      end;constructor Ta.Create;
    begin
      arr[0]:=0;arr[1]:=0;
      inherited Create(False)
    end;
    procedure Ta.Execute;
    begin
      FreeOnTerminate := True;
      while not Terminated do
      begin
      arr[0]:=1;arr[1]:=2;
      OutputDebugString(PChar(format('thread%d: %d,%d', [ThreadID, arr[0],arr[1]])));
      Sleep(1000);
      end;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      Ta.Create;
      Ta.Create;
    end;
      

  3.   

    行,大家帮我看看代码:unit WYCSThrd;interfaceuses
       Windows, Messages,SysUtils,Forms,ADODB,DB,Dialogs,RzDBEdit,popForm,DBGridEh,DBGrids,
         ComObj,StdCtrls,Graphics,Classes, StrUtils, Registry, IniFiles, RzDBGrid, Math,  Controls, ComCtrls,ExtCtrls,DateUtils;type
        SendArr = Array[0..7] of byte;
        RevArr = Array of byte;
        PRevArr = ^RevArr;
      TWYCSThrd = class(TThread)
      private
        { Private declarations }
        TPort: longint;
        DevType,DevTypeName: String;
        qry1,qry2,qry3,qry4 : TADOQuery;
        MonitJG : Integer;
        CanTerminated : boolean;
        jzfieldname,jzdsdata,jzbj,arcsdm : array[0..80] of string;//数据错乱的数组  protected
        procedure Execute; override;
        function datajx(rev: array of byte) : boolean;
        procedure savedata;
        
      public
        constructor Create(Suspended: Boolean; Port: Longint; SBLXDM: String; smjg : Integer);
        destructor Destroy; override;
        
        function getCanTerminated : boolean;
      end;implementation
     uses PComm,dataModule,public_unit;var
        senddata:SendArr;
        revdata : RevArr;
        prev    : PRevArr;
        CS     :    TRTLcriticalsection;  
        OldMonth : Integer; 
        tablename : String;
    { Important: Methods and properties of objects in visual components can only be
      used in a method called using Synchronize, for example,      Synchronize(UpdateCaption);  and UpdateCaption could look like,    procedure TWYCSThrd.UpdateCaption;
        begin
          Form1.Caption := 'Updated in a thread';
        end; }{ TWYCSThrd }constructor TWYCSThrd.Create(Suspended: Boolean; Port: Integer;
      SBLXDM: String; smjg : Integer);
    var
         i : integer;
         sdate : String;
    begin
      inherited Create(Suspended);
      FreeOnTerminate := True;  TPort := Port;
      DevType := SBLXDM;
      DevTypeName := DevName;
      MonitJG := smjg;
      
      DateTimeToString(sdate, 'YYYYMM', now());
      OldMonth := StrToInt(sdate);  
      sbdm := '';
      fieldnum := 0;
      dcfloop  := 0;
      loopednum := 1;
      DCLoopNum := 1;  looped := true;
      赋初值
      for i:= 0 to 79 do begin
          jzfieldname[i]:= '';
          jzdsdata[i]   := '';
          jzbj[i]       := '';
          arcsdm[i]     := '';
      end;
      getDCNUM;
      tablename :=getTableNameH('BWYDdata');
      if not getTableHExit(tablename) then
          CreateTableH(tablename);
    end;
    function TWYCSThrd.datajx(rev: array of byte): boolean;
    var
        sqlstr,fieldname : string;
        dw,bjz : string;
        jxkz,gsdm : Integer;
        bl ,calResult    : double;
        i,n : integer;
        bitarr:array of integer;
        xsz,xsj : string;
        bjkz : Integer;
        intarr : array of Integer;
        sx,xx : double;//报警值上下线
    begin    try
        qry2 := TADOQuery.Create(Application.Owner);
        qry2.Connection := frmDataModule.WYConn;    setlength(bitarr, regDataNum);
        setlength(intarr, regDataNum*2);
        dw := '';
        if(rev[1]=1) or (rev[1]=2) then
        begin
            n := 0;
            for i:= 0 to  regDataNum-1 do begin
                bitarr[i] := (rev[3+n] AND (1 shl (i-n*8))) shr (i-n*8);
                if (i>0) and (((i+1) mod 8)=0) then
                    n:= n+1;
            end;
        end
        else if(rev[1]=3) or (rev[1]=4) then
        begin
           n := 0;
           for i:= 0 to  regDataNum-1 do begin
              intarr[i] := rev[3+i*2]*256+ rev[4+i*2];
           end;    end;
        
        sqlstr := 'select * from WDYLCSJXB where mldm='+quotedstr(mldm);
        with qry2 do begin
           close;
           SQL.Clear;
           SQL.Add(sqlstr);
           open;
        end;
        i := 0;
        n := 0;
        while not qry2.eof do begin
        jxkz := qry2.FieldByname('jxkz').AsInteger;
        if  ( jxkz=0) then
        begin
           i:= i+1;
           qry2.Next;
           continue;
        end
        else  begin //30
            jxkz := qry2.FieldByname('jxkz').AsInteger;
            gsdm := qry2.FieldByName('gsdm').AsInteger;
            if(not qry2.FieldByName('dw').IsNull) then
                 dw   := qry2.FieldByName('dw').AsString;
            bl   := qry2.FieldByName('bl').AsFloat;
            fieldname := qry2.FieldByName('FieldName').AsString;        if qry2.FieldByname('bjkz').AsBoolean = true then
                bjkz := 1
            else
                bjkz := 0;
            bjz :=  qry2.FieldByname('bjz').AsString;
            if ((rev[1]=3) or (rev[1]=4)) and  ( jxkz=1) then begin//15
                jzfieldname[fieldnum] :=  fieldname;
                if gsdm=5 then begin
                    calResult := calcFunction(intarr[i],0,0,0,qry2);
                    jzdsdata[fieldnum]:= Floattostr(calResult)+dw;
                end;
                if bjkz=1 then  begin //17
                if pos('-',bjz)>0 then begin
                  sx := strToFloat(copy(bjz,0,pos('-',bjz)-1));
                  xx := StrtoFloat(copy(bjz,pos('-',bjz)+1,length(bjz)-pos('-',bjz)));
                  if (calResult>=xx) or  (calResult<=sx) then
                     jzbj[fieldnum] := '报警'
                  else
                     jzbj[fieldnum] := '正常';
                end
                else begin
                  if (calResult=strtoint(bjz)) then
                     jzbj[fieldnum] := '报警'
                  else
                     jzbj[fieldnum] := '正常';            end;            end; //17            fieldnum := fieldnum+1;
                i:= i+1;
             end;  //15
             qry2.Next;
            end; //30
            
            end;// end while    if Jugeloopover then begin
            savedata;
            for i:= 0 to 79 do begin
              jzbj[i]       := '';
            end;
            fieldnum := 0;
            loopednum := 1;
        end;
         result:= true;
         finally
             qry2.Close;
             qry2.Free;
             qry2 := nil;
         end;
    end;destructor TWYCSThrd.Destroy;
    begin
      sio_close(TPort);
      inherited;
    end;procedure TWYCSThrd.Execute;
    var
       sqlstr : string;
       datalenth,ret,jgsj : Integer;
       startAdd : Integer;
       olddate,newdate : TDateTime;
    begin
      { Place thread code here }
      try
      initializeCriticalsection(CS);   //增加 临界区初始化
      qry1 := TADOQuery.Create(Application.Owner);
      qry1.Connection := frmDataModule.WYConn;
      olddate := now();
      CanTerminated := true;
      while not Terminated do begin
      CanTerminated := true;
      if looped then begin
           looped := false;
           WYrefresh := false;
           CanTerminated := false;
           sqlstr := 'select * from FunctionInfo where mldm like '+quotedstr(DevType+'%');
           with qry1 do begin
              close;
              SQL.Clear;
              SQL.Add(sqlstr);
              open;
           end;
           while not qry1.Eof do begin
               mldm := qry1.FieldByname('mldm').AsString;
             
               senddata[0] := qry1.FieldByname('sbid').AsInteger;
               senddata[1] := qry1.FieldByname('Funct').AsInteger;           regDataNum := qry1.FieldByName('DataLenth').AsInteger;
               startAdd   := qry1.FieldByName('startAdd').AsInteger;
               ret := write(senddata,startAdd,regDataNum);
               if(ret=8) then begin
                  sleep(40);
                  getRevinfo(senddata[1],qry1.FieldByName('DataLenth').AsInteger);
                  ret := read(revDataLength+5,@revdata);
                  if(ret = 1) then
                  begin
                     prev :=  @revdata;
                     datajx(prev^);
                  end;
               end;
               qry1.Next;
           end;
           qry1.Close;
           CanTerminated := true;  end
      else if looped=false then
         CanTerminated := true;
         newdate := now();
         jgsj := SecondsBetween(newdate,olddate);
         if(jgsj>=MonitJG) then begin
            try
               SetprocessWorkingSetSize(GetCurrentProcess,$FFFFFFFF,$FFFFFFFF);
            finally
               application.ProcessMessages ;
            end;
            looped := true;
            olddate := now;
         end;
         CanTerminated := true;
         application.ProcessMessages ;
         sleep(50);  end;
     
       finally
           sio_close(TPort);
           qry1.Free;
           qry1 := nil;
           Deletecriticalsection(cs);  //增加 临界区初始化
       end;
    end;function TWYCSThrd.getCanTerminated: boolean;
    begin
       if CanTerminated then
            result := true
        else
            result := false;
    end;procedure TWYCSThrd.savedata;     //  lst修改 20120401
    var
       i,newMonth : Integer;
       sqlstr : string;
       sdate : string;
    begin
       try
       //对 最新月份赋值
       DateTimeToString(sdate, 'YYYYMM', now());
       newMonth := StrToInt(sdate);
       qry4 := TADOQuery.Create(Application.Owner);
       qry4.Connection := frmDataModule.WYConn;
       tablename :=getTableNameH('BWYDdata');
       // 跨月时,添加表   if(newMonth>OldMonth) then begin   //11111
        //锁定操作,使线程同步
           EnterCriticalsection(cs);
           if not getTableHExit(tablename) then
                CreateTableH(tablename);
                OldMonth := NewMonth;
                LeaveCriticalsection(cs);
           end;  ///1111   
                 //可以完全拷贝    111--111区间       sqlstr := 'select * from '+tablename+' where id=(select max(id) from '+tablename+')';
           with qry4 do begin
                close;
                sql.Clear;
                sql.Add(sqlstr);
                open;
           end;       qry4.Append;
           qry4.Edit;
           qry4.FieldByName('sbdm').AsString := sbdm;
           qry4.FieldByName('time_send').AsString := DateTimetoStr(now);       for i:= 0 to fieldnum-1 do begin
             // 这里报错,jzfieldname[i]为空,相互干扰了
              qry4.FieldByName(jzfieldname[i]).AsString := jzdsdata[i];
              qry4.FieldByName(jzfieldname[i]+'bj').AsString := jzbj[i];
           end;
           qry4.UpdateBatch;
           WYrefresh := true;
       finally
          qry4.Close;
          qry4.Free;
          qry4 := nil;
       end;
    end;
    end.
      

  4.   

       prev :=  @revdata;
       datajx(prev^);已经操作非局部代码了