如何锁定记录数组以在线程中添加和删除元素
How can lock array of records for adding and deleting element in thread
我想一次又一次地从服务器获取一些查询,并在记录数组中列出这个 URL 查询。
要释放内存,必须释放处理的数组元素。
这个进程在线程上,防止App卡死。
如果数组未锁定,则删除元素可能会引发异常,因为其他元素正在处理中,或者添加或删除元素的索引已更改。
我的问题是:‘如何锁定用于在线程中添加和删除元素的记录数组?’
为了理解我的实际 App 代码,简化了此示例代码:
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.
您可以使用锁来保护对共享数据的访问,然后在您访问数据的所有地方的一般模式是:
Lock.Enter;
try
// procected code
finally
Lock.Leave;
end;
您需要在与需要保护的数据相同的范围内声明锁变量,并且您需要在第一次使用之前初始化该锁,并在不再需要时释放它。
比如你的MyRecAra
是unit中的全局数据,那么Lock
也需要是全局的,在unit的initialization部分初始化,在finalization部分release。
如果 MyRecAra
是表单中的字段或其他 class,那么 Lock
也将是 class 中的字段,在构造函数中初始化并在析构函数中释放.
常用的锁是TCriticalSection
。还有其他类型的锁,但作为开始,这个就可以了。
var
Lock: TCriticalSection;
MyRecAra: TMyRecAra;
initialization
Lock := TCriticalSection.Create;
finalization
Lock.Free;
end.
我想一次又一次地从服务器获取一些查询,并在记录数组中列出这个 URL 查询。
要释放内存,必须释放处理的数组元素。 这个进程在线程上,防止App卡死。 如果数组未锁定,则删除元素可能会引发异常,因为其他元素正在处理中,或者添加或删除元素的索引已更改。
我的问题是:‘如何锁定用于在线程中添加和删除元素的记录数组?’
为了理解我的实际 App 代码,简化了此示例代码:
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.
您可以使用锁来保护对共享数据的访问,然后在您访问数据的所有地方的一般模式是:
Lock.Enter;
try
// procected code
finally
Lock.Leave;
end;
您需要在与需要保护的数据相同的范围内声明锁变量,并且您需要在第一次使用之前初始化该锁,并在不再需要时释放它。
比如你的MyRecAra
是unit中的全局数据,那么Lock
也需要是全局的,在unit的initialization部分初始化,在finalization部分release。
如果 MyRecAra
是表单中的字段或其他 class,那么 Lock
也将是 class 中的字段,在构造函数中初始化并在析构函数中释放.
常用的锁是TCriticalSection
。还有其他类型的锁,但作为开始,这个就可以了。
var
Lock: TCriticalSection;
MyRecAra: TMyRecAra;
initialization
Lock := TCriticalSection.Create;
finalization
Lock.Free;
end.