问题是这样的:
一个列表A,我要遍历A中的每个条目,如果遍历的过程中发现某个条目的情况不理想,我就会删除这个条目,同时外部还有可能增加条目。大概如下
for i := 0 to AList.Count - 1 do
begin
if AList[i] = 某种逻辑 then
Delete[i];
//同时外部有 Alist.Add(。)
end;
大概就这么情况,这样如何保证AList的访问安全性?求助。
这个问题我想大家多多少少都碰到过,希望大家多多拋玉,谢谢了!
一个列表A,我要遍历A中的每个条目,如果遍历的过程中发现某个条目的情况不理想,我就会删除这个条目,同时外部还有可能增加条目。大概如下
for i := 0 to AList.Count - 1 do
begin
if AList[i] = 某种逻辑 then
Delete[i];
//同时外部有 Alist.Add(。)
end;
大概就这么情况,这样如何保证AList的访问安全性?求助。
这个问题我想大家多多少少都碰到过,希望大家多多拋玉,谢谢了!
for i := AList.Count - 1 to 0 do
begin
if AList[i = 某种逻辑 then
Delete[i];
//同时外部有 Alist.Add(。)
end;]
2、使用同步技术
比如现在的List依次存储着A,B,C,D,
for i := ALst.Count - 1 downto 0 do
begin
//这种情况对于在D后面增加元素没有关系,
//但是程序在收到消息可能在处理D的时候,就删除掉A,B,C
//现在面临的情况是,List中前面的元素可能被删除,后面的元素可能增加
//不知道用什么算法比较合适
end;
另外要用downto否则会报错的
被临界区或者synchronize保护的列表除非你让出使用权,否则其他修改的程序处于阻塞状态
推荐用数据库存储列表内容,他很好的解决了互斥等问题,不要自己写循环遍历,直接从库中读取列表内容进行修改和添加等操作,如果出于显示需要,你再写入list就可以了
synchronize是用在线程中的函数或者方法上,表示该方法执行时,其中使用的变量不能被其他线程使用
临界区可以用在公用变量里,也就是多个线程试图访问一个临界区内的变量时,会进入阻塞状态,只有一个线程可以进入临界区,直到那个临界区释放其他线程才能进入
如果说你只是要循环判断并且删除或修改其中的某条记录的话可以把整个判断代码放到临界区里,当然要注意1判断和修改时间不能过长,2 结束后释放临界区,3 所有试图访问该列表的代码都要用临界区包起来,4 尽量避免多线程死锁
给你个例子
VCL实现同步的另一种方法就是调用线程类的Synchronize的过程,此过程需要一个无参数的procedure,故在此procedure中无法传递参数值,但可以通过类的成员来实现。在类的Execute中只须调用Synchronize就可以了。实现: 关键在于对Synchronize参数的定义。定义一个无参数的procedure通过它来访问类的成员变量szName和nIndex。在类的重载Execute中调用Synchronize。子类的定义如下:
unit TChildThread;interfaceuses =Classes,Messages,Windows,SysUtils;const MAX_LEN = 260;typeTChildThreads = class(TThread)private { Private declarations }protectedprocedure Execute; override;//同步函数的声明
procedure UpdateData;public szName : array[0..MAX_LEN] of Char; nIndex : Integer;end;implementationuses Unit1;{ Important: Methods and properties of objects in VCL or CLX can only be usedin a method called using Synchronize, for example, Synchronize(UpdateCaption);and UpdateCaption could look like, procedure TChildThread.UpdateCaption; begin Form1.Caption := 'Updated in a thread'; end; }{ TChildThread }//同步函数的实现procedure TChildThreads.UpdateData;begin Form1.ShowData.Items.Add(PChar(@szName));end;procedure TChildThreads.Execute;begin{ Place thread code here }//调用同步过程Synchronize(UpdateData);end;end.
主程的设计与《Delphi中多线程用消息实现VCL数据同步显示》基本一致,但为了与其显示相同结果,在生成子线程中语句顺序作了一下调整。以下代码仅显示与上一篇不同的一个过程,其它代码不再赘述。
procedure TForm1.StartThreadsClick(Sender: TObject);var oChildThread : array[0..1000] of TChildThreads;i : Integer;begin For i := 0 to 1000 dobegin oChildThread[i] := TChildThreads.Create(true); //注意这里的代码与消息同步中的顺序。 oChildThread[i].nIndex := i; strcopy(@oChildThread[i].szName,PChar('Child' + IntToStr(i))); oChildThread[i].Resume;end;end;===============================================另一个例子:http://topic.csdn.net/t/20011015/02/323001.html unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Image1: TImage;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TMyThread = class(TThread)
private
child : TComponent;
public
procedure draw;
constructor Create(parent : TComponent);
procedure Execute; override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TMyThread }
constructor TMyThread.Create(parent: TComponent);
begin
child := parent;
inherited Create(false);
end;
procedure TMyThread.draw;
begin
if (child is TEdit) then
begin
(child as TEdit).Text := 'OK';
end
else if(child is TImage) then
begin
(child as TImage).Canvas.Brush.Color := clBlue;
(child as TImage).Canvas.FillRect(rect(0,0,100,100));
end;
end;
procedure TMyThread.Execute;
begin
inherited;
synchronize(draw);
if Terminated then Exit;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TMythread.Create(Edit1);
TMythread.Create(image1);
end;
不考虑外部,也应倒序遍历来删
如果是多线程的,应该使用一个线程安全的list:Tthreadlist