Home > other >  How can lock array of records for adding and deleting element in thread
How can lock array of records for adding and deleting element in thread

Time:12-21

I want to get some query from server time by time and list this URL query on the array of records.

For freeing of memory must free the elements of an array that procced. This process is on the thread to prevent freezing of App. If the array is not locked, maybe deleting of element rise exception because that other element is in process or adding or deleting an index of element changed.

My question is: ’How can I lock an array of records for adding and deleting an element in the thread?’

This sample code is simplified for understanding my actual App code:

uses  IdHTTP;

type 
  tMyRecAra=record
    sta:integer;
    url:string;
    // ...
    // ...
  end;

var MyRecAra: array of tMyRecAra;

procedure TfoTestAra.btAddClick(Sender: TObject);
var cou:integer;
begin
  //  start lock array MyRecAra ?
    cou:=length(MyRecAra);
    SetLength(MyRecAra, length(MyRecAra) 1);
    MyRecAra[cou].sta:=0;
    MyRecAra[cou].url:='http:/......';
  //- stop lock array MyRecAra ?    
end;

procedure TfoTestAra.btStartClick(Sender: TObject);
var
  IdHTTP1:TIdHTTP;
  mainThr,curThr : TThread;
  cStream:TMemoryStream;
begin
  mainThr := TThread.CreateAnonymousThread(
    procedure
      begin
        while true {or other condition}  do
          begin
            curThr := TThread.CreateAnonymousThread(
              procedure
              var i:integer;
              begin
                //  start lock array MyRecAra ?
                  for i := 0 to (length(MyRecAra)-1) do
                    begin
                      if (MyRecAra[i].sta=0) then
                        begin
                          MyRecAra[i].sta:=1;
                          //...
                          //..
                           {for example : IdHTTP1.Get(MyRecAra[i].url,cStream)};
                          //...
                          //..
                        end;
                      end;
                //- stop lock array MyRecAra ?
              end);
            curThr.Start;
            sleep(5000);
          end;
      end);
  mainThr.start;
end;

procedure TfoTestAra.Timer1Timer(Sender: TObject);
var 
  sumFee:integer;
  i, j:integer;
begin
  // timer.interval=10000;

  //  start lock array MyRecAra?
    sumFee:=0;
    for i := 0 to (length(MyRecAra)-1) do
    begin
      if (MyRecAra[i].sta=1) then
        begin
          inc(sumFee);
          for j := (i 1) to  sumFee-1 do
            begin
              if  (MyRecAra[j].sta <> 1) then
                MyRecAra[i]:=MyRecAra[j]
            end;

        end;
      end;
      if sumFee<>0 then
        SetLength(MyRecAra, (length(MyRecAra)-sumFee));
   //  stop lock array MyRecAra ?
end;

End.

CodePudding user response:

You can use lock to protect access to shared data and then general pattern in all places where you access the data would be:

Lock.Enter;
try
  // procected code
finally
  Lock.Leave;
end;

You need to declare lock variable in the same scope as the data that needs protection and you need to initialize that lock before it is used for the first time and free it when it is no longer needed.

For instance, if your MyRecAra is global data in unit, then Lock also needs to be global and initialized in initialization section of the unit and released in finalization section.

If MyRecAra is field in form or some other class, then Lock would also be a field in that class, initialized in constructor and released in destructor.

Commonly used lock is TCriticalSection. There are other types of locks, but for start this one will do just fine.

var
  Lock: TCriticalSection;
  MyRecAra: TMyRecAra; 

initialization

  Lock := TCriticalSection.Create;

finalization

  Lock.Free;

end.
  • Related